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

时间:2008-09-11 13:15:19

标签: c++ c interop name-decoration

我坚持修复传统的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;

正如托尼(以及我之前尝试过的)所建议的那样导致了不同的预期装饰,但仍然没有将其删除:

未解析的外部符号__imp__MyNewVariable

如何编写声明,以便可以从C app访问C ++ DLL变量?


答案

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

7 个答案:

答案 0 :(得分:5)

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

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

答案 1 :(得分:4)

extern“C”是你如何删除装饰 - 它应该可以使用:

extern“C”declspec(dllimport)char MyNewVariable;

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

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

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

答案 2 :(得分:2)

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

答案 3 :(得分:1)

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

答案 4 :(得分:1)

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

答案 5 :(得分:1)

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

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

c客户端应在此声明中使用标头,以便客户端代码导入符号:

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

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

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

#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;

答案 6 :(得分:0)

我在Windows中编程时从未使用过__declspec(dllimport)。你应该能够简单地声明

extern "C" char* MyNewVariable;

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