If you need a simple C export, use a C project, not C ++. C ++ DLLs rely on name processing for all CMS names (namespaces, etc.). You can compile your code as C by going to your project settings in the C / C ++ → Advanced section, there is the “Compile As” option, which coordinates the compiler keys / TP and / TC.
Export / Import DLLs in VC ++
What you really want to do is define a conditional macro in the header that will be included in all the source files in your DLL project:
#ifdef LIBRARY_EXPORTS # define LIBRARY_API __declspec(dllexport) #else # define LIBRARY_API __declspec(dllimport) #endif
Then for the function you want to export, you use LIBRARY_API
:
LIBRARY_API int GetCoolInteger();
In the library assembly project, create define LIBRARY_EXPORTS
, this will cause your functions to be exported for your DLL assembly.
Since LIBRARY_EXPORTS
will not be defined in a project using the DLL when this project includes your library header file, all functions will be imported instead.
If your library needs to be cross-platform, you can define LIBRARY_API as nothing if not on Windows:
#ifdef _WIN32 # ifdef LIBRARY_EXPORTS # define LIBRARY_API __declspec(dllexport) # else # define LIBRARY_API __declspec(dllimport) # endif #elif # define LIBRARY_API #endif
When using dllexport / dllimport you do not need to use DEF files, if you use DEF files you do not need to use dllexport / dllimport. The two methods perform the same task in different ways, I think dllexport / dllimport is the recommended method of the two.
Export non-confused functions from C ++ DLL for LoadLibrary / PInvoke
If you need to use LoadLibrary and GetProcAddress, or possibly make PInvoke from .NET, you can use the extern "C"
inline with your dllexport. And since we use GetProcAddress instead of dllimport, we do not need to make an ifdef tank on top, just a simple dllexport:
The code:
#define EXTERN_DLL_EXPORT extern "C" __declspec(dllexport) EXTERN_DLL_EXPORT int getEngineVersion() { return 1; } EXTERN_DLL_EXPORT void registerPlugin(Kernel &K) { K.getGraphicsServer().addGraphicsDriver( auto_ptr<GraphicsServer::GraphicsDriver>(new OpenGLGraphicsDriver()) ); }
And this is what export looks like with Dumpbin / exports:
Dump of file opengl_plugin.dll File Type: DLL Section contains the following exports for opengl_plugin.dll 00000000 characteristics 49866068 time date stamp Sun Feb 01 19:54:32 2009 0.00 version 1 ordinal base 2 number of functions 2 number of names ordinal hint RVA name 1 0 0001110E getEngineVersion = @ILT+265(_getEngineVersion) 2 1 00011028 registerPlugin = @ILT+35(_registerPlugin)
So this code works fine:
m_hDLL = ::LoadLibrary(T"opengl_plugin.dll"); m_pfnGetEngineVersion = reinterpret_cast<fnGetEngineVersion *>( ::GetProcAddress(m_hDLL, "getEngineVersion") ); m_pfnRegisterPlugin = reinterpret_cast<fnRegisterPlugin *>( ::GetProcAddress(m_hDLL, "registerPlugin") );