如果要纯C导出,请使用C项目而不是C ++。C ++ DLL依赖于所有C ++语言(名称空间等)的名称处理。您可以进入C / C ++-> Advanced下的项目设置,将代码编译为C,其中有一个选项“ Compile As”,对应于编译器开关/ TP和/ TC。
如果您仍然想使用C ++来编写您的lib的内部结构,但是要导出一些未拼凑的函数以在C ++之外使用,请参见下面的第二部分。
在VC ++中导出/导入DLL库
您真正想要做的是在标头中定义一个条件宏,该标头将包含在您的DLL项目的所有源文件中:
#ifdef LIBRARY_EXPORTS
# define LIBRARY_API __declspec(dllexport)
#else
# define LIBRARY_API __declspec(dllimport)
#endif
然后在要导出的函数上使用LIBRARY_API
:
LIBRARY_API int GetCoolInteger();
在您的库构建项目中创建一个定义,LIBRARY_EXPORTS
这将导致您的函数为DLL构建导出。
由于LIBRARY_EXPORTS
不会在使用DLL的项目中定义,因此当该项目包含库的头文件时,所有功能将改为导入。
如果您的库是跨平台的,则可以在不在Windows上时将LIBRARY_API定义为空:
#ifdef _WIN32
# ifdef LIBRARY_EXPORTS
# define LIBRARY_API __declspec(dllexport)
# else
# define LIBRARY_API __declspec(dllimport)
# endif
#elif
# define LIBRARY_API
#endif
使用dllexport / dllimport时,不需要使用DEF文件;如果使用DEF文件,则不需要使用dllexport / dllimport。两种方法以不同的方式完成同一任务,我相信dllexport / dllimport是这两种方法中的推荐方法。
从C ++ DLL导出未损坏的函数以进行LoadLibrary / PInvoke
如果需要使用LoadLibrary和GetProcAddress,或者从另一种语言(例如,.NET的PInvoke或Python / R中的FFI等)导入,则可以extern "C"
将dllexport内联使用,以告诉C ++编译器不要弄乱名称。而且由于我们使用的是GetProcAddress而不是dllimport,所以我们不需要从上面进行ifdef跳舞,只需一个简单的dllexport:
代码:
#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())
);
}
这是用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)
所以这段代码可以正常工作:
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")
);
extern C
将删除描述函数参数类型的修饰符,而不是描述函数调用约定的修饰符;b)要删除所有修饰,您需要在DEF文件中指定(未修饰的)名称。