|
Mig's HomePage
Personal page of Michal Mig Novotný
|
|
Writing DLL libraries under Linux Writing winapps under Linux Testing Windows applications under Linux Using LoadLibrary() to load DLL libraries |
If you want to write dynamically linked libraries (DLL) for Windows under Linux based operating systems you have to have mingw32 packages mingw32-runtime, mingw32-binutils and mingw32-gcc installed first. The binutils package is required for dlltool. After installing those packages you have to write the source code having the __declspec(dllexport) defined for functions you want to export from this DLL library. Here's an example of such a source code file called testlib.c: #include <stdio.h> #ifdef BUILDING_DLL #define DLLEXPORT __declspec(dllexport) #else #define DLLEXPORT __declspec(dllimport) #endif DLLEXPORT int testsquare(int a) { return a * a; }Now when you have the source code you need to compile it for Windows systems using the mingw32 gcc. First we compile it with the following command: i686-pc-mingw32-gcc -o testlib.dll -mdll testlib.c -Wl,--out-implib,libtestlib.a -DBUILDING_DLLand then we have the library ready to be used. Alternatively you could use following two commands to generate the object file first and then later generate the binary from the object file using: i686-pc-mingw32-gcc -c -o testlib.o testlib.c -DBUILDING_DLL i686-pc-mingw32-gcc -o testlib.dll -mdll testlib.o -Wl,--out-implib,libtestlib.aPlease note presence of BUILDING_DLL define there which makes the source compile with __decl(dllexport) to export the library function to be publicly visible and therefore accessible from applications. Now we should be having testlib.dll and libtestlib.a files generated which are both necessary to compile the application that will be using this library.
For writing Windows applications under Linux we need packages as written above, for using the DLLs in your applications you need the DLL library along with the library file *.a. This is an example how to write an application using the library we have created above in Writing DLL libraries under Linux article. Creating such an application is the same as writing standalone application that's using a shared library but you will most likely have to provide location using -L<location> directive to the compiler/linker to point the linker to the directory with the library and library file.
Here's an example of such a source code file called test.c: #include <stdio.h> int main(int argc, char *argv[]) { printf("TestSquare(5): %d\n", testsquare(5)); return 0; }To compile this you have to use the following command: i686-pc-mingw32-gcc -o test.exe test.c -ltestlib -L<location>which would create the file test.exe that's using the testlib.dll library to compute testsquare value.
After you create both library and the application you should test it to confirm everything is working fine. Under Linux you should use either Wine to emulate or, if you have the Windows virtual machine, you could test it in the Windows VM. If you would like to use Wine you will need Wine packages (downloadable from winehq.org) and after installing it you can run the Windows application using:
wine ./test.exe This example command assumes your Windows executable file is called test.exe and you should be having result like: $ wine ./test.exe TestSquare(5): 25 $When the executable resides in the same directory like the required library. If the required library is not found you will see the error message like: $ wine ./test.exe err:module:import_dll Library testlib.dll (which is needed by L"Z:\\home\\{path}\\test.exe") not found err:module:LdrInitializeThunk Main exe initialization for L"Z:\\home\\{path}\\test.exe" failed, status c0000135 $This error message can be fixed by copying the library (here called testlib.dll) to the same directory. When you try to run the same application under Windows but you omit to include the library you will see th error message 1114 (saying An initialization routine of a dynamic library (DLL) failed.) or something similar to this. If you don't know whether the library will be available or not and your application doesn't require it to it's proper functionality and the library is just adding some new features to your application, like when your library is just a plug-in module, you should consider using LoadLibrary() API function instead. First of all, you need to include the windows.h and winbase.h header files to your application to be able to access WinAPI functions and then you should create a HMODULE handle to handle the library itself. The function to be loaded should be having it's typedef and the variable to be used should to carry the function pointer be defined at the beginning. Then your code should be having LoadLibrary(), GetProcAddress() and FreeLibrary() calls (in that order) with error checking whether the library and function could be found there or not etc. The code for ... #include <windows.h> #include <winbase.h> int main() { HMODULE lib = NULL; typedef int (WINAPI *pTestSquare)(int); pTestSquare pTS = NULL; lib = LoadLibrary("testlib.dll"); if (!lib) { printf("Cannot load specified library testlib.dll\n"); return 1; } pTS = (pTestSquare) GetProcAddress(lib, "testsquare"); if (pTS != NULL) printf("TestSquare(5): %d\n", pTS(5)); else printf("TestSquare export not found in testlib.dll library\n"); FreeLibrary(lib); return 0; }To compile this you have to use the following command: i686-pc-mingw32-gcc -o test.exe test.cThis will create the test.exe executable file with no requirement for testlib.dll library. When you run this application but the library won't be available the error message that library cannot be found will be and application will return with error code 1. |