Using S3E Library to dynamically load libraries
Since almost 7 months now I'm working on an application called GOFG Sports Computer (GOFG stands for 'Get On Fat Guy') which is an OpenSource sports tracking software for your mobile device. As I wanted the application to be cross platform and compatible to as many devices as possible I decided to use a commercial SDK called AirplaySDK (see http://www.airplaysdk.com/ for details).
The SDK offers a great API for loading external (native) libraries on several platforms which allows usage of functionality not covered by the standard Airplay APIs. However documentation on how exactly that functionality is used and how to correctly call external library functions from within your AirplaySDK code is not available (at least not in detail).
After some fiddling and trial & error coding I finally have a working version and I wanted to share that knowledge with everyone. So here we go:
First of all you need to be familiar with function pointers in C and you should know what Symbols are in the context of a library. As I've written my code for Windows based devices (both Windows and Windows Mobile) the examples outlined here illustrate the use with Windows dlls, but should be applicable for any other OS too.
Before you can actually use any function within your AirplaySDK code, you need to define a valid function pointer for the signature of the target function. Lets assume the function you want to use is CreateFile (official MSDN documentation can be found here). The signature of it is rather complex and the main problem here is that custom types defined by the windows API are used. However doing some research revealed that most of the custom types are simple typedefs for primitive C data types. More details on the data-types of windows can be found here.
Once you translated all the datatypes into C primitives you can define the function pointer. For our example, the CreateFile function, the function pointer will look like the following:
/** HANDLE WINAPI CreateFile( __in LPCTSTR lpFileName, __in DWORD dwDesiredAccess, __in DWORD dwShareMode, __in_opt LPSECURITY_ATTRIBUTES lpSecurityAttributes, __in DWORD dwCreationDisposition, __in DWORD dwFlagsAndAttributes, __in_opt HANDLE hTemplateFile ); */ typedef void*(*win_createFile)(const wchar_t*, unsigned long, unsigned long, void*, unsigned long, unsigned long, void* );
The first part shows the original definition from the MSDN, the typedef shows the signature within "pure" C.
So now the function signature is defined within our AirplaySDK environment. All we now need to do is load the DLL and fetch the correct Symbol from the DLL and cast it so that we can call it using the signature we just defined. This is done quite easily:
s3eDLLHandle windowsDll = s3eExtLibraryOpen( "kernel32" ); win_createFile cfHandle = (win_createFile) s3eExtLibraryGetSymbol( windowsDll, "CreateFileW" );
As you can see loading the library is done use s3eExtLibraryOpen and passing the name of the dll to it (NOTE: I did not find out so far if you have to specify the exact path or not, on windows mobile it seems to be enough if you just specify the name, on windows I had to use the absolute path).
Once we have the s3eDLLHandle we can use it to fetch a certain symbol from the DLL. This is done using s3eExtLibraryGetSymbol. This is pretty straightforward as well, just pass the s3eDLLHandle and the name of the Symbol to the function. If you do not know the name of the symbol, you can use a tool like dumpbin to fetch a list of symbols within a DLL.
s3eExtLibraryGetSymbol returns a void Pointer that's why we need to explicitly cast it to our function. Now we can use cfHandle to actually call the function:
cfHandle( (const wchar_t*) "test.txt", 0x80000000, 0, NULL, 3, 0x80, 0 );
However if you are familiar with C function pointers this should be easy for you.
I hope this blog entry helps other developers safe time since it took me quite a while to work out all details and finally test & prove that everything works as IÂ would expect it.
In the meantime I'm already using several functions from the Windows API to extend the capabilities of AirplaySDK. If you should ask why I need CreateFile - simply because CreateFile can be used to read from Serial-Ports which is not supported by AirplaySDK so far...