Exporting functions from a DLL with dllexport
dll, name-decoration, visual-c++, winapi
Solution
If you want plain C exports, use a C project not C++. C++ DLLs rely on name-mangling for all the C++isms (namespaces etc...). You can compile your code as C by going into your project settings under C/C++->Advanced, there is an option "Compile As" which corresponds to the compiler switches /TP and /TC.
If you still want to use C++ to write the internals of your lib but export some functions unmangled for use outside C++, see the second section below.
Exporting/Importing DLL Libs in VC++
What you really want to do is define a conditional macro in a header that will be included in all of the source files in your DLL project:
#ifdef LIBRARY_EXPORTS
# define LIBRARY_API __declspec(dllexport)
#else
# define LIBRARY_API __declspec(dllimport)
#endif
Then on a function that you want to be exported you use `LIBRARY_API`:
LIBRARY_API int GetCoolInteger();
In your library build project create a define `LIBRARY_EXPORTS` this will cause your functions to be exported for your DLL build.
Since `LIBRARY_EXPORTS` will not be defined in a project consuming the DLL, when that project includes the header file of your library all of the functions will be imported instead.
If your library is to be cross-platform you can define LIBRARY_API as nothing when 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 accomplish the same task different ways, I believe that dllexport/dllimport is the recommended method out of the two.
Exporting unmangled functions from a C++ DLL for LoadLibrary/PInvoke
If you need this to use LoadLibrary and GetProcAddress, or maybe importing from another language (i.e PInvoke from .NET, or FFI in Python/R etc) you can use `extern "C"` inline with your dllexport to tell the C++ compiler not to mangle the names. And since we are using GetProcAddress instead of dllimport we don't need to do the ifdef dance from above, 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 here's what the exports look 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")
);
Problem
I'd like a simple example of exporting a function from a C++ Windows DLL. I'd like to see the header, the `.cpp` file, and the `.def` file (if absolutely required). I'd like the exported name to be undecorated. I'd like to use the most standard calling convention (`__stdcall`?). I'd like the use `__declspec(dllexport)` and not have to use a `.def` file. For example: ``` //header extern "C" { __declspec(dllexport) int __stdcall foo(long bar); } //cpp int __stdcall foo(long bar) { return 0; } ``` I'm trying to avoid the linker added underscores and/or numbers (byte counts?) to the name. I'm OK with not supporting `dllimport` and `dllexport` using the same header. I don't want any information about exporting C++ class methods, just c-style global functions. UPDATE Not including the calling convention (and using `extern "C"`) gives me the export names as I like, but what does that mean? Is whatever default calling convention I'm getting what pinvoke (.NET), declare (vb6), and `GetProcAddress` would expect? (I guess for `GetProcAddress` it would depend on the function pointer the caller created). I want this DLL to be used without a header file, so I don't really need the a lot of the fancy `#defines` to make the header usable by a caller. I'm OK with an answer being that I have to use a `*.def` file.