Symbian
Symbian Developer Library

SYMBIAN OS V9.4

Feedback

[Index] [Previous] [Next]


Dynamic Link Libraries

[Top]


Definition

A Dynamic Link Library (DLL) contains executable code which can be shared by many processes in a system at any one time. A program can link against a DLL at compile time, meaning that the linker will match the DLL's symbols (such as function names and variables) with references from the program and ascertain the address within the DLL of the functions or variables.

Alternatively a program can dynamically load a DLL into memory during execution, locate the address of a symbol, use it and then unload the DLL.

Traditionally and for greater memory efficiency, Symbian OS links by ordinal, whereas Unix-like operating systems link by name. The following sections provide example code to illustrate how the DLL loader works with each operating system.

[Top]


Shared libraries in a Unix-like environment

The following code shows how a shared library is dynamically loaded and used in a Unix-like environment using the 'dl' interface.

int main(int argc, char *argv[])
{
  //Handle
  void* dll_handle;

  //Function prototype
  void (*printSum)(int a, int b);

  //Error message
  const char* errorMsg;
 
  //Filename of dll to load 
  char dllFileName[] = "/root/PortDoc/Example6/dll/shareddll";

  //Load the dll
  dll_handle = dlopen(dllFileName, RTLD_LAZY);
  if (!dll_handle)
  {
     fprintf(stderr, "Error during load of library: %s\n", dlerror()); 
     return EXIT_FAILURE;
  }

  //Find the symbol
  printSum = dlsym(dll_handle, "printSum");   

  //Get the error message 
  errorMsg = dlerror();
  if (errorMsg)
  {
     fprintf(stderr, "Error during symbol lookup: %s\n", errorMsg);
     return EXIT_FAILURE;
  } 

  //Now call the function
  printSum(4, 6);

  //Dispose of the DLL
  dlclose(dll_handle);

  return EXIT_SUCCESS;
}

As an example, the shareddll might have a function such as:

void printSum(int a, int b)
{
  printf("Result is : %d\n", a + b);
}

[Top]


DLLs on Symbian OS Using P.I.P.S. (pre-Symbian OS v9.3)

Symbian OS programs uses the function or variable's ordinal position within a DLL to link with DLLs. For example, implementing a shared DLL on Symbian OS could look like this:

EXPORT_C void printSum(int a, int b)
{
  printf("Result is : %d\n", a + b);
}

Compiling this will generate a .def file, which contains the ordinals of each symbol in the DLL. For instance,

EXPORTS
    printSum @ 1 NONAME

where the .def shows that the ordinal for the printSum() function is 1. The following code shows how the main() program is now changed in P.I.P.S..

int main(int argc, char *argv[])
{
  //Handle
  void* dll_handle;

  //Function prototype
  void (*printSum)(int a, int b);

  //Error message
  const char* errorMsg;
 
  //Filename of dll to load 
  char dllFileName[] = "/root/PortDoc/Example6/dll/shareddll";

  //Load the dll
  dll_handle = dlopen(dllFileName, RTLD_LAZY);
  if (!dll_handle)
  {
     fprintf(stderr, "Error during load of library: %s\n", dlerror()); 
     return EXIT_FAILURE;
  }

  //Find the symbol, using the ordinal
  printSum = dlsym(dll_handle, "1");   

  //Get the error message 
  errorMsg = dlerror();
  if (errorMsg)
  {
     fprintf(stderr, "Error during symbol lookup: %s\n", errorMsg);
     return EXIT_FAILURE;
  } 

  //Now call the function
  printSum(4, 6);

  //Dispose of the DLL
  dlclose(dll_handle);

  return EXIT_SUCCESS;
}

Note that for the Symbian library loader, the mode parameter for the dlopen() function is irrelevant and the library will be loaded immediately. So although RTLD_LAZY is the mode parameter in the example, it will behave just as RTLD_NOW. Also note that there is no facility to call any library constructor and destructor functions using __attribute((constructor)) or __attribute((destructor)).

[Top]


DLLs on Symbian OS Using P.I.P.S. (Symbian OS v9.3 onwards)

P.I.P.S. provides APIs from libdl to support dynamic lookup by name, which is used in Unix-like platforms, instead of the native Symbian OS lookup by ordinal mechanism. Lookup by name is possible thanks to the new libdl, which in turn uses the existing RLibrary functions to load and unload DLLs.

A symbol name lookup version of the dlsym() function is provided, similar to UNIX®, which does not need any special treatment (the example shown in Shared libraries in a Unix-like environment will suffice). However, it is still necessary to generate the .def file for the DLL.


libdl APIs

The libdl APIs, which support dynamic lookup by name, are described in the following sections.

void *dlopen (const char *path, int mode)

Call dlopen() to gain access to symbols of any shared library or DLL. If dlopen() fails for any reason, it will return a NULL. The default search path for the library can be provided in the environment variable LD_LIBRARY_PATH.

void *dlsym(void *handle, const char *symbol)

The dlsym() function returns the address binding of the symbol described in the null-terminated character string 'symbol', as it occurs in the shared object identified by 'handle'.

int dlclose(void *handle)

Call dlclose() with a valid dlopen-ed handle to remove it from the cache list maintained by dlopen(). If it fails, dlclose() will return -1; otherwise, it will return 0.

char *dlerror(void)

Call dlerror() to obtain the most recent error that occurred due to any of the dl routines, that is, dlopen(), dlsym(), or dlclose().

[Top]


Also see