This is my first time dealing with DLLs. Following the MSDN documentation I created a header file fooExports.h with macros defined according to a preprocessor definition:
#ifdef FOODLL_EXPORTS
#define FOO_API __declspec( dllexport )
#else
#define FOO_API __declspec( dllimport )
My intention was to use this header both in my DLL implementation as well as in the console application. So far importing and exporting functions works just fine. The problem arrises when I try to export an already defined struct that I need as parameter for one of the exported functions. For example, in the aforementioned header file I declare FOO_API void foo( FooParams *args )
and args
is a struct defined as follows:
typedef struct FooParams
{
char *a;
char *b;
void *whatever; //some other type
} FooParams;
This struct has to be defined in foo.h rather than in fooExports.h. Is there any way to export this struct without taking it out of it's original header file (taking into consideration that I want to keep the exports/imports centralized in fooExports.h). What would be a better approach to doing this? The DLL is all C as well as the client application using it.
If the only use the client will ever have for FooParams
is to get pointers to it returned from DLL functions and to pass those pointers to other DLL functions, you can make it an "opaque type": Put
typedef struct FooParams FooParams;
in fooExports.h. The FOO_API
macro does not belong on that declaration. An opaque type means the client code cannot:
FooParams
(but FooParams * ptr = NULL;
is okay).FooParams
.sizeof(FooParams)
- and therefore cannot correctly malloc
space for one or more FooParams
objects.You can't #define
macros visible to the client which do any of the above, either. So your DLL would need to have one or more "constructor" or "factory" functions, maybe something like
FOO_API FooParams* CreateFooParams(const char * input);
It's also good practice to define a matching "destructor" function like
FOO_API void DestroyFooParams(FooParams * p);
even if the definition is as simple as { free(p); }
, because there can sometimes be issues if memory allocated inside a DLL is freed by code outside it or vice versa (because not all Windows code uses identical definitions of malloc
and free
).
If all this is too extreme, the only other option is to put or #include
the struct
definition in the exported header file and make it visible to clients. Without that, any attempt to do something to a FooParams
, other than passing pointers around, is going to be impossible because the compiler won't know what's in a FooParams
. The compiler (as opposed to the linker) takes information only from commandline arguments and #include
-d files, not from libraries or DLLs.