无法访问 C 中的变量 来自 C 应用程序的 DLL

发布于 2024-07-04 16:45:26 字数 776 浏览 7 评论 0原文

我一直在修复旧版 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 应用程序访问 C++ DLL 变量?


答案

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

I'm stuck on a fix to a legacy Visual C++ 6 app. In the C++ DLL source I have put

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

which results in MyNewVariable showing up (nicely undecorated) in the export table (as shown by dumpbin /exports blah.dll). However, I can't figure out how to declare the variable so that I can access it in a C source file. I have tried various things, including

_declspec(dllimport) char* MyNewVariable;

but that just gives me a linker error:

unresolved external symbol "__declspec(dllimport) char * MyNewVariable" (__imp_?MyNewVariable@@3PADA)

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

as suggested by Tony (and as I tried before) results in a different expected decoration, but still hasn't removed it:

unresolved external symbol __imp__MyNewVariable

How do I write the declaration so that the C++ DLL variable is accessible from the C app?


The Answer

As identified by botismarius and others (many thanks to all), I needed to link with the DLL's .lib. To prevent the name being mangled I needed to declare it (in the C source) with no decorators, which means I needed to use the .lib file.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

故人爱我别走 2024-07-11 16:45:26

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

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

you must link against the lib generated after compiling the DLL. In the linker options of the project, you must add the .lib file. And yes, you should also declare the variable as:

extern "C" { declspec(dllimport) char MyNewVariable; }
朦胧时间 2024-07-11 16:45:26

extern "C" 是删除装饰的方法 - 它应该可以使用:

extern "C" declspec(dllimport) char MyNewVariable;

或者如果您想要一个可由 C++ 或 C 使用的标头(带有 /TC 开关)

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

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

extern "C" is how you remove decoration - it should work to use:

extern "C" declspec(dllimport) char MyNewVariable;

or if you want a header that can be used by C++ or C (with /TC switch)

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

And of course, link with the import library generated by the dll doing the export.

半岛未凉 2024-07-11 16:45:26

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

I'm not sure who downmodded botismarius, because he's right. The reason is the .lib generated is the import library that makes it easy to simply declare the external variable/function with __declspec(dllimport) and just use it. The import library simply automates the necessary LoadLibrary() and GetProcAddress() calls. Without it, you need to call these manually.

乄_柒ぐ汐 2024-07-11 16:45:26

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

They're both right. The fact that the error message describes __imp_?MyNewVariable@@3PADA means that it's looking for the decorated name, so the extern "C" is necessary. However, linking with the import library is also necessary or you'll just get a different link error.

只有一腔孤勇 2024-07-11 16:45:26

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

@Graeme: You're right on that, too. I think the "C" compiler that the OP is using is not enforcing C99 standard, but compiling as C++, thus mangling the names. A true C compiler wouldn't understand the "C" part of the extern "C" keyword.

-黛色若梦 2024-07-11 16:45:26

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;

In the dll source code you should have this implementation so that the .lib file exports the symbol:

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

The c client should use a header with this declaration so that the client code will import the symbol:

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

This header will cause a compile error if #include-ed in the dll source code, so it is usually put in an export header that is used only for exported functions and only by clients.

If you need to, you can also create a "universal" header that can be included anywhere that looks like this:

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

Then the dll source code looks like this:

#define dll_source_code 
#include "universal_header.h"

EXPORTED char* MyNewVariable = 0;

And the client looks like this:

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

If you do this a lot, the monster #ifdef at the top can go in export_magic.h and universal_header.h becomes:

#include "export_magic.h"

EXPORTED char *MyNewVariable;
紙鸢 2024-07-11 16:45:26

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

extern "C" char* MyNewVariable;

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

I've never used _declspec(dllimport) when I was programming in Windows. You should be able to simply declare

extern "C" char* MyNewVariable;

and link to the .libb created when DLL was compiled.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文