8

我坚持修复旧版 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 文件。

4

7 回答 7

5

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

extern "C" { declspec(dllimport) char MyNewVariable; }
于 2008-09-11T13:22:07.170 回答
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 生成的导入库。

于 2008-09-11T13:20:37.003 回答
3

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

于 2008-09-11T13:34:55.113 回答
1

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

于 2008-09-11T13:36:46.217 回答
1

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

于 2008-09-11T13:40:44.443 回答
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;
于 2008-09-11T16:37:08.823 回答
0

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

extern "C" char* MyNewVariable;

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

于 2008-09-11T14:17:44.790 回答