Turning an application into a DLL

WildW

Senior member
Oct 3, 2008
984
20
81
evilpicard.com
I've been asked to turn the application I'm working on (C++/wxWidgets/OpenGL developed in Dev-C++) into a DLL to be called from another program.

Essentially it's a graphical frontend to a simulation, which until now has been called by passing parameters at the command line or via a text file to a separate exe. The developers of the simulation would like the whole frontend program to be a DLL they can call up from their program, and I'm not sure where to start.

The only time I've ever written a DLL before was to call a C function from Visual Basic, many many moons ago. I wasn't even aware that it was possible to call something this complex as a DLL.

Can anyone point me towards a good guide on doing something like this please?
 

degibson

Golden Member
Mar 21, 2008
1,389
0
0
Unfortunately I don't have any windows-specific advice to offer, just some general stuff:

- A DLL is just code. Your DLL will probably be your entire codebase, except for main() and whatever tests you have.
- You have to pick / have the privilege of picking what the external interface. DLLs don't export every function call -- Decide what it should look like. There will probably be some special decoration you put on exposed interfaces, a __declspec in all likelihood.
- Your initial target should be the exact functionality you already have. Your current binary should start up, load your DLL, and then do whatever it does already. That's a good initial built-in test for your DLL.
- A program is only a program because of how it is linked. A DLL is just linked a little differently. There's nothing all that special about what code goes in a DLL.
 

brandonb

Diamond Member
Oct 17, 2006
3,731
2
0
It's been along time since I've done a .dll from scratch (using C++). I do remember, atleast with MSVS, that you need to call the functions LoadLibrary and GetProcAddress from the host app. And then implement a DLL project with DllMain in the DLL. That lets you know when something has attached to the DLL. Then I believe you just create functions within the DLL that get exposed to the host with the GetProcAddress. My memory is sort of fuzzy, but I believe the functions you want to expose go into a .def file. I'm not sure it requires much of anything else, it was actually pretty simple.

Not sure how this is done wtih Dev-C++
 
Last edited:

Cogman

Lifer
Sep 19, 2000
10,283
134
106
1. Dump Dev-C++, dump it now. It has been dead for over 5 years now. There is no good reason to still be using it (I have also ran into stability issues). Get a good IDE like Visual studios or Code::blocks. Code::blocks is especially a good replacement for dev-c++ if you want things to feel similar.

2. As degibson said, DLLs are just code. If you want to use it, then you need (ok, you don't NEED it, but it makes things easier to work with) header files with all the functions you want to work with. Functions to be exported have __declspec(dllexport). Functions to be imported have __declspec(dllimport) in their definitions. This is usually resolved with a macro that looks something like this
Code:
#ifdef BUILD_DLL
    #define DLL_EXPORT __declspec(dllexport)
#else
    #define DLL_EXPORT __declspec(dllimport)
#endif

3. Besides the export import stuff, you'll also need a DLL main function. Those are usually pretty generic. Here is an example
Code:
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
    switch (fdwReason)
    {
        case DLL_PROCESS_ATTACH:
            // attach to process
            // return FALSE to fail DLL load
            break;

        case DLL_PROCESS_DETACH:
            // detach from process
            break;

        case DLL_THREAD_ATTACH:
            // attach to thread
            break;

        case DLL_THREAD_DETACH:
            // detach from thread
            break;
    }
    return TRUE; // successful
}
These are fairly generic as it is basically only handling how the DLL i to behave when hooking in.

4. While it is possible to do, avoid exporting classes. GCC, Microsoft, delph, et al. implement class standards differently (the C++ standard allows it). You have the distinct possibility of ending up in a world of hurt if you don't heed this warning.

5. Use stdcall when possible. Again, calling conventions can really screw you over. About the only one guaranteed to be implemented the same across the board is stdcall. In MSVC I believe it is __stdcall but in gcc it is __attribute__(stdcall) or something like that (if you googled what I type, it would come up). You loose the ability to use the ellipsis... I, however, doubt you have ever used it (and if you have, you are doing things wrong).

6. I can already see this in your future, since you are dealing with a gui. DLLs and GUIs don't generally play nicely together. That is because Win32 guis have things like message pumps in them which sort of make it difficult to put in a DLL. It is possible, but not advisable. If you MUST do it, then starting your gui in a new thread is pretty much a requirement. Unfortunately, this isn't something that is so simple where you can just send messages to the gui and have it do what you want.

I'll be frank, for this reason alone, DLLs pretty much NEVER have any graphical interface code in them (IE they don't create windows). But if you absolutely must, be prepared for a hellish experience. Windows does not allow anyone but the creating thread to call functions the modify windows resources for that thread. That means you can't intercept messages for the GUI, and you can't do things like change the position of a button. That all has to be handled by the thread that created those windows. You can call the function that gets fired on a button push, so long as it doesn't change the way the window looks (or tries to access information about the window elements) This presents a nice problem because libraries such as wxWidgets go to great lengths to hide all code specific to windows. So you really don't know when a function will touch something i shouldn't.

Whats worse, you can't change the way the message loop behaves with wxWidgets. You are stuck with their message loop. What you can do, is use the Windows PostMessage API to send messages to the thread, but you get the wonderful opportunity of finding out exactly how the messagepump works if you want to rely on that.
 

WildW

Senior member
Oct 3, 2008
984
20
81
evilpicard.com
Ahh, there's the type of answer I was secretly looking for; the "are you crazy!?!" response.

Dev-C++ is just because whoever started this thing X years and Y programmers ago used it. I am finding it quite hateful, and the debugger doesn't work, at all. I had a 30min go at trying to get the code together in Visual Studio a while back, but didn't have much success. Will have to try it again.

As for the more DLL issues, you're making this task sound nightmarish. My program is essentially a 3D OpenGL environment that displays the position of various entities as time varies. Mouse is used to scroll/rotate with a bunch of dialog windows to tweak various things. I suppose it might be a viable compromise to remove much of this functionality when called as a DLL, but if that means two diverging sets of code it's probably a bad idea.

I shall ponder quoting your reponse in an email to my boss and try to kill the idea off.


1. Dump Dev-C++, dump it now. It has been dead for over 5 years now. There is no good reason to still be using it (I have also ran into stability issues). Get a good IDE like Visual studios or Code::blocks. Code::blocks is especially a good replacement for dev-c++ if you want things to feel similar.

2. As degibson said, DLLs are just code. If you want to use it, then you need (ok, you don't NEED it, but it makes things easier to work with) header files with all the functions you want to work with. Functions to be exported have __declspec(dllexport). Functions to be imported have __declspec(dllimport) in their definitions. This is usually resolved with a macro that looks something like this
Code:
#ifdef BUILD_DLL
    #define DLL_EXPORT __declspec(dllexport)
#else
    #define DLL_EXPORT __declspec(dllimport)
#endif

3. Besides the export import stuff, you'll also need a DLL main function. Those are usually pretty generic. Here is an example
Code:
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
    switch (fdwReason)
    {
        case DLL_PROCESS_ATTACH:
            // attach to process
            // return FALSE to fail DLL load
            break;

        case DLL_PROCESS_DETACH:
            // detach from process
            break;

        case DLL_THREAD_ATTACH:
            // attach to thread
            break;

        case DLL_THREAD_DETACH:
            // detach from thread
            break;
    }
    return TRUE; // successful
}
These are fairly generic as it is basically only handling how the DLL i to behave when hooking in.

4. While it is possible to do, avoid exporting classes. GCC, Microsoft, delph, et al. implement class standards differently (the C++ standard allows it). You have the distinct possibility of ending up in a world of hurt if you don't heed this warning.

5. Use stdcall when possible. Again, calling conventions can really screw you over. About the only one guaranteed to be implemented the same across the board is stdcall. In MSVC I believe it is __stdcall but in gcc it is __attribute__(stdcall) or something like that (if you googled what I type, it would come up). You loose the ability to use the ellipsis... I, however, doubt you have ever used it (and if you have, you are doing things wrong).

6. I can already see this in your future, since you are dealing with a gui. DLLs and GUIs don't generally play nicely together. That is because Win32 guis have things like message pumps in them which sort of make it difficult to put in a DLL. It is possible, but not advisable. If you MUST do it, then starting your gui in a new thread is pretty much a requirement. Unfortunately, this isn't something that is so simple where you can just send messages to the gui and have it do what you want.

I'll be frank, for this reason alone, DLLs pretty much NEVER have any graphical interface code in them (IE they don't create windows). But if you absolutely must, be prepared for a hellish experience. Windows does not allow anyone but the creating thread to call functions the modify windows resources for that thread. That means you can't intercept messages for the GUI, and you can't do things like change the position of a button. That all has to be handled by the thread that created those windows. You can call the function that gets fired on a button push, so long as it doesn't change the way the window looks (or tries to access information about the window elements) This presents a nice problem because libraries such as wxWidgets go to great lengths to hide all code specific to windows. So you really don't know when a function will touch something i shouldn't.

Whats worse, you can't change the way the message loop behaves with wxWidgets. You are stuck with their message loop. What you can do, is use the Windows PostMessage API to send messages to the thread, but you get the wonderful opportunity of finding out exactly how the messagepump works if you want to rely on that.