|
||
This example application shows a simple EXE and DLL written using
P.I.P.S. (P.I.P.S. Is POSIX on Symbian OS). It also shows the dynamic lookup of
symbols by name mechanism used in Unix-like operating systems, instead of the
native Symbian OS lookup by ordinal mechanism. P.I.P.S., from Symbian OS v9.3,
provides APIs from libdl
library to implement this lookup by name
mechanism.
The example defines a simple DLL using the P.I.P.S. STDDLL
target type, with an exported function. It also creates a simple EXE, using the
STDEXE
target type, which calls the DLL's exported function using
the lookup by name mechanism. These P.I.P.S. specific target types are required
to enable the specific options for compilers and linkers to generate P.I.P.S.
executables and to make symbol information available in the executable image.
This example is located in examples\PIPS\HelloWorldExample
.
The example creates a DLL file that declares and defines an exported
function. The target type of this DLL file is STDDLL
. It contains
a header and a source file:
helloworlddllexample.h
: this declares a function
with external linkage. Note that for a STDDLL
library, functions
and data with external linkage are exported by default, without any requirement
for IMPORT_C
and EXPORT_C
declarations in header or
source files.
helloworlddllexample.cpp
: this defines the function
declared in the header file, which displays a hello world message to the
console.
The example creates an EXE file which calls the exported function of
the loaded DLL. The target type of this EXE file is STDEXE
. It
calls the following libdl
functions to use the lookup by name
mechanism:
dlopen()
: This function is used to load the
DLL file which contains an exported function.
dlsysm()
: This function gets the address of
a symbol defined within the DLL loaded by the dlopen()
call.
dlclose()
: This function informs the system
that the DLL loaded by a previous dlopen()
call is no longer
needed by the application.
dlerror()
: This function is used to get the
last error that occurred from any of the libdl
APIs.
The EXE links to libdl.lib
to use these functions.
The Symbian OS build process describes how to build this example application.
The HelloWorldExample
builds two files, a DLL file
helloworlddllexample.dll
, and an EXE file
helloworldexeexample.exe
, in the standard locations.
To run the example, start helloworldexeexample.exe
from
the file system or from your IDE. After launching the executable, depending on
the emulator you are using, you may need to navigate away from the application
launcher or shell screen to view the console.
// bld.inf
// Component description file
//
// Copyright (c) 2007 Symbian Ltd. All rights reserved.
PRJ_PLATFORMS
DEFAULT
PRJ_EXPORTS
PRJ_MMPFILES
helloworlddllexample.mmp
helloworldexeexample.mmp
// helloworlddllexample.mmp
//
// Copyright (C) Symbian Software Ltd 2007. All rights reserved
TARGET helloworlddllexample.dll
TARGETTYPE STDDLL
UID 0x20004C45 0xE80000C5
CAPABILITY NONE
VENDORID 0x70000001
SOURCEPATH ..\src\helloworlddllexample
SOURCE helloworlddllexample.c
SYSTEMINCLUDE \epoc32\include
USERINCLUDE ..\inc\helloworlddllexample
LIBRARY libc.lib
STATICLIBRARY libcrt0.lib
// helloworldexeexample.mmp
//
// Copyright (C) Symbian Software Ltd 2007. All rights reserved.
TARGET helloworldexeexample.exe
TARGETTYPE STDEXE
UID 0x20004C45 0xE80000C6
CAPABILITY NONE
SOURCEPATH ..\src\helloworldexeexample
SOURCE helloworldexeexample.c
SYSTEMINCLUDE \epoc32\include
USERINCLUDE ..\inc\helloworldexeexample
LIBRARY libc.lib
LIBRARY libdl.lib
STATICLIBRARY libcrt0.lib
// helloworlddllexample.h
//
// Copyright (C) Symbian Software Ltd 2007. All rights reserved.
#ifndef __HELLOWORLDDLLEXAMPLE_H__
#define __HELLOWORLDDLLEXAMPLE_H__
// Declaration of an export function.
extern void PrintHelloWorld();
#endif //__HELLOWORLDDLLEXAMPLE_H__
// helloworldexeexample.h
//
// Copyright (C) Symbian Software Ltd 2007. All rights reserved.
#ifndef __HELLOWORLDEXEEXAMPLE_H__
#define __HELLOWORLDEXEEXAMPLE_H__
// Declaration of functions defined in the source file.
void PressAKey();
int DisplayErrorMessage();
#endif //__HELLOWORLDEXEEXAMPLE_H__
// helloworlddllexample.cpp
//
// Copyright (C) Symbian Software Ltd 2007. All rights reserved.
// This example is a simple PIPS STDDLL application that contains the export function definition.
#include "helloworlddllexample.h"
#include <stdio.h>
/*
Definition of the export function declared in the header file.
This function prints a welcome message.
*/
void PrintHelloWorld()
{
char str[90]=" Welcome to HelloWorld Basic EXE and DLL example, using symbolic name lookup\n";
printf("%s",str);
getchar();
}
// helloworldexeexample.c
//
// Copyright (C) Symbian Software Ltd 2007. All rights reserved.
/* This example is a simple PIPS STDEXE application. It loads the DLL and calls its exported function.
The application implements the dynamic lookup by name mechanism of the exported function using the libdl APIs.
*/
// Include files.
#include <stdio.h>
#include <dlfcn.h>
#include <stdlib.h>
/**
Waits for key press event.
*/
void PressAKey()
{
fflush(stdout);
getchar();
}
/**
Get and display the most recent error that occurred due to any of the dynamic lookup routines.
@return EXIT_FAILURE Returns the failure code.
*/
int DisplayErrorMessage()
{
// Obtain the last error occurred using the libdl API, dlerror().
const char *q = dlerror();
// Prints the error message.
printf("%s");
PressAKey();
// returns the failure code.
return EXIT_FAILURE;
}
int main()
{
int result;
// Handle to load the dynamic library.
void* handleToDll;
typedef void (*PrintHelloWorldFunction)(void);
PrintHelloWorldFunction PrintHelloWorld;
// Contains name of the DLL file.
char dllFileName[] = "helloworlddllexample.dll";
/**
Loads the DLL using the libdl API dlopen(), to gain access to the symbols in it.
It takes two parameters: the name of the DLL file and the mode in which it has to be loaded.
This returns a NULL, if it fails for any reason.Otherwise, it returns a descriptor.
*/
handleToDll = dlopen(dllFileName, RTLD_LAZY);
// Check the descriptor value.If it is null, the error message is printed.
if (!handleToDll)
{
DisplayErrorMessage();
}
// Print the message to start the example application.
printf(" Press enter key to step through the example application\n");
PressAKey();
/**
Locates the symbol using the libdl API, dlsym().
It takes the handle returned by the dlopen() function and the symbol name to find.
This returns the address binding of the symbol, PrintHelloWorld if successful. Otherwise, it returns NULL.
*/
PrintHelloWorld = (PrintHelloWorldFunction)dlsym(handleToDll, "PrintHelloWorld");
// Check the symbol address value. If this is null, the error message is printed.
if(!PrintHelloWorld)
{
DisplayErrorMessage();
}
// Call the loaded DLL's exported function.
PrintHelloWorld();
/**
Remove the dlopen-ed handle from the cache, maintained by dlopen(), using libdl API, dlclose().
It takes the handle returned by the dlopen() function to decrement the reference count associated with the DLL.
When the reference count reaches zero, the DLL is unloaded from the process address space.
This API returns 0 if successful, otherwise it returns -1.
*/
result= dlclose(handleToDll);
// Check the return value. If this is -1, the error message is printed.
if(result == -1)
{
DisplayErrorMessage();
}
// Print the message to exit from the example application.
printf(" Press enter key to exit from the example application");
PressAKey();
// returns the success code.
return EXIT_SUCCESS;
}