无法从C应用程序访问C ++ DLL中的变量

我坚持修复传统的Visual C ++ 6应用程序。 在我放的C ++ DLL源代码中

extern "C" _declspec(dllexport) char* MyNewVariable = 0; 

这导致MyNewVariable在导出表中显示(很好地未修饰)(如dumpbin / exports blah.dll所示)。 但是,我无法弄清楚如何声明变量,以便我可以在C源文件中访问它。 我尝试了各种各样的东西,包括

 _declspec(dllimport) char* MyNewVariable; 

但这只是给我一个链接器错误:

未解析的外部符号“__declspec(dllimport)char * MyNewVariable”(__ imp_?MyNewVariable @@ 3PADA)

 extern "C" _declspec(dllimport) char* MyNewVariable; 

正如Tony所建议的(以及我之前尝试过的)会产生不同的预期装饰,但仍未删除它:

未解析的外部符号__imp__MyNewVariable

如何编写声明,以便可以从C应用程序访问C ++ DLL变量?


答案

由botismarius和其他人确认(非常感谢所有),我需要链接DLL的.lib。 为了防止名称被破坏,我需要声明它(在C源代码中)没有装饰器,这意味着我需要使用.lib文件。

你必须链接编译DLL后生成的lib。 在项目的链接器选项中,必须添加.lib文件。 是的,你还应该将变量声明为:

 extern "C" { declspec(dllimport) char MyNewVariable; } 

extern“C”是你如何删除装饰 – 它应该工作使用:

extern“C”declspec(dllimport)char MyNewVariable;

或者如果你想要一个可以被C ++或C使用的头文件(带/ TC开关)

 #ifdef __cplusplus extern "C" { #endif declspec(dllimport) char MyNewVariable; #ifdef __cplusplus } #endif 

当然,还要与执行导出的dll生成的导入库链接。

我不确定是谁修改了botismarius,因为他是对的。 原因是生成的.lib是导入库,它可以很容易地使用__declspec(dllimport)简单地声明外部变量/函数并使用它。 导入库只是自动执行必要的LoadLibrary()GetProcAddress()调用。 没有它,您需要手动调用它们。

他们都是对的。 错误消息描述__imp_?MyNewVariable@@3PADA意味着它正在寻找装饰名称,因此extern“C”是必要的。 但是,与导入库链接也是必要的,否则您将获得不同的链接错误。

@Graeme:你也是对的。 我认为OP使用的“C”编译器不是强制执行C99标准,而是编译为C ++,因此会破坏名称。 真正的C编译器不会理解extern "C"关键字的“C”部分。

dll源代码中,您应该具有此实现,以便.lib文件导出符号:

 extern "C" _declspec(dllexport) char* MyNewVariable = 0; 

c客户端应该使用带有此声明的标头 ,以便客户端代码将导入符号:

 extern "C" _declspec(dllimport) char* MyNewVariable; 

如果在dll源代码中包含#include-ed,则此标头将导致编译错误,因此通常将其放在导出标头中,该标头仅用于导出的function,并且仅由客户端使用。

如果需要,您还可以创建一个“通用”标题,可以包含在以下任何位置:

 #ifdef __cplusplus extern "C" { #endif #ifdef dll_source_file #define EXPORTED declspec(dllexport) #else #define EXPORTED declspec(dllimport) #endif dll_source_file #ifdef __cplusplus } #endif EXPORTED char* MyNewVariable; 

那么dll源代码如下所示:

 #define dll_source_code #include "universal_header.h" EXPORTED char* MyNewVariable = 0; 

客户端看起来像这样:

 #include "universal_header.h" ... MyNewVariable = "Hello, world"; 

如果你这么做了,顶部的怪物#ifdef可以进入export_magic.h并且universal_header.h变为:

 #include "export_magic.h" EXPORTED char *MyNewVariable; 

我在Windows编程时从未使用_declspec(dllimport)。 你应该能够简单地宣布

 extern "C" char* MyNewVariable; 

并链接到编译DLL时创建的.libb。