C++ dll problem

Cogman

Lifer
Sep 19, 2000
10,286
147
106
Ok, so heres my problem.

I have a DLL that I am making to simulate another development environment (a bunch of pascal functions) part of that development environment is the ability to have plugins that are able to add new functions to the environment.

I want this thing to be as compatible as possible. Getting the function name is not a problem, nor is getting its address. The problem arises when I want to make the function callable from a users program. Heres an example of what I want to happen.

I Create a DLL with several functions in it.
User A: creates a DLL with function B, puts it in a plugin folder.
User B: has User A's function but only wants to call it through my dll, but doesn't want to load their dll and search for the function.

Like I said, each plugin DLL has a function (by the same name) that will return the name and address of each function in the dll. What I want to do is make it so that those functions are available as if they where part of the original dll.
 

SunnyD

Belgian Waffler
Jan 2, 2001
32,675
146
106
www.neftastic.com
extern "C" __declspec(dllexport) ... in the DLL's version of the header

extern "C" __declspec(dllimport) ... in the "client's" version of the header

For example, say you have a function Foo you want to put in a DLL... the header prototype will be something like this:

extern "C" __declspec(dllexport) void Foo(void);

And in the "client" application you would import the function as such:

extern "C" __declspec(dllimport) void Foo(void);

A few things to note, make sure calling conventions match up (cdecl, stdcall, fastcall or naked). Usually people define a header that handles both exports and imports that rely on a preprocessor declaration:

#ifndef __FOO_IMPORT // If __FOO_IMPORT isn't define then we're building the DLL
#define __FOO_CALL extern "C" __declspec(dllexport)
#else // You've defined __FOO_IMPORT so you're using the header in a client app (assumedly)
#define __FOO_CALL extern "C" __declspec(dllimport)
#endif // __FOO_IMPORT

__FOO_CALL void Foo(void);

And in your project/makefile you would define __FOO_IMPORT for client projects, this would allow you to reuse the same header for both the DLL and clients.

(note: some of this may be syntactically different depending on what C++ compiler you're using)
 

Cogman

Lifer
Sep 19, 2000
10,286
147
106
Originally posted by: SunnyD
extern "C" __declspec(dllexport) ... in the DLL's version of the header

extern "C" __declspec(dllimport) ... in the "client's" version of the header

For example, say you have a function Foo you want to put in a DLL... the header prototype will be something like this:

extern "C" __declspec(dllexport) void Foo(void);

And in the "client" application you would import the function as such:

extern "C" __declspec(dllimport) void Foo(void);

A few things to note, make sure calling conventions match up (cdecl, stdcall, fastcall or naked). Usually people define a header that handles both exports and imports that rely on a preprocessor declaration:

#ifndef __FOO_IMPORT // If __FOO_IMPORT isn't define then we're building the DLL
#define __FOO_CALL extern "C" __declspec(dllexport)
#else // You've defined __FOO_IMPORT so you're using the header in a client app (assumedly)
#define __FOO_CALL extern "C" __declspec(dllimport)
#endif // __FOO_IMPORT

__FOO_CALL void Foo(void);

And in your project/makefile you would define __FOO_IMPORT for client projects, this would allow you to reuse the same header for both the DLL and clients.

(note: some of this may be syntactically different depending on what C++ compiler you're using)

is there a way to do this without requiring the client to write a header for their DLLs? Most don't have headers available. (though, they wouldn't be extremely hard to write)
 

EagleKeeper

Discussion Club Moderator<br>Elite Member
Staff member
Oct 30, 2000
42,589
5
0
Without the header, the DLL may not know which functions need to be setup for external use.

The internal usage of the file may be from previously seen during parsing (similar to C and C++
It is the definitioin of functions available for export that determines how the DLL will work.

One can build the headers by cut/paste of the source code that is to be exported.
 

Cogman

Lifer
Sep 19, 2000
10,286
147
106
Originally posted by: Common Courtesy
Without the header, the DLL may not know which functions need to be setup for external use.

The internal usage of the file may be from previously seen during parsing (similar to C and C++
It is the definitioin of functions available for export that determines how the DLL will work.

One can build the headers by cut/paste of the source code that is to be exported.

*sigh* I was afraid of that. The reason the program Im trying to mimic can get away with it is because it uses a late compile type philosophy (So programs are distributed as source and compiled from the IDE).

So, I guess that means its header writing time for me :D. At least the IDE specified a function that must be present in the plugins to barf out their names, address, ect.
 

SunnyD

Belgian Waffler
Jan 2, 2001
32,675
146
106
www.neftastic.com
Originally posted by: Cogman
is there a way to do this without requiring the client to write a header for their DLLs? Most don't have headers available. (though, they wouldn't be extremely hard to write)

Oh heck yes. The key is that you're still going to have to write/develop an API of your own to manage it. You may think of it as the plug-in will be packaged in a DLL, the DLL will have a standard interface to adhere to for discovery of the plug-in's functionality.

Basically what I've just described is more or less called COM. :)

Essentially you're looking to do something like Trillian or Firefox do for plug-ins. All DLL's have a standard sort of "interface" used to initialize them. Pretty much you'd still need some common function that the client will use to discover functionality, but as long as each "function" can deliver it's calling format (parameters, etc) you're fine.

Something like: Application Runs --> Checks Plugin Folder --> See's file named MyPlugIn.dll --> Attempts to load MyPlugIn.dll --> Calls a standardized method to discover functions in DLL (eg: EnumerateFunctions()) --> Populates a table with function pointers and parameter types returned by the enumeration --> Functionality becomes exposed in the main application.

The key is that "EnumerateFunctions" and the format of the data it returns must be strictly enforced. If the EnumerateFunctions function doesn't exist, has a wrong signature or does whacky stuff, the DLL likely isn't a Plug-in (or is corrupted?), so move along and ignore it. Any plug in would have to adhere to strict standards when it comes to the EnumerateFunctions call and then you would also expect that any function exposed adheres to however it is described by EnumerateFunctions. The key is that you would have to design this construct and mechanism yourself.

Or as I said, take a look at COM... it does a good portion of this for you (it's not EXACTLY what you want, but it will get you going).

(I should note that in C++ you'll still likely need headers unless you really know what you're doing - which I can't claim to on this one)