无法访问 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;
按照托尼的建议(以及我之前尝试过的)导致不同的预期装饰,但仍未删除它:
未解析的外部符号 __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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
您必须链接到编译 DLL 后生成的库。 在项目的链接器选项中,您必须添加
.lib
文件。 是的,您还应该将变量声明为: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" 是删除装饰的方法 - 它应该可以使用:
extern "C" declspec(dllimport) char MyNewVariable;
或者如果您想要一个可由 C++ 或 C 使用的标头(带有 /TC 开关)
,当然,还可以链接到执行导出的 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)
And of course, link with the import library generated by the dll doing the export.
我不确定是谁下调了 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 necessaryLoadLibrary()
andGetProcAddress()
calls. Without it, you need to call these manually.他们都是对的。 事实上,错误消息描述
__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.@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.在 dll 源代码中,您应该具有此实现,以便 .lib 文件导出符号:
c 客户端应使用带有此的标头声明以便客户端代码将导入符号:
如果在dll源代码中#include-ed,此标头将导致编译错误,因此通常将其放在仅用于以下目的的导出标头中导出函数并且只能由客户端使用。
如果需要,您还可以创建一个“通用”标头,可以包含在任何地方,如下所示:
然后 dll 源代码如下所示:
客户端如下所示:
如果您经常这样做,怪物 #顶部的 ifdef 可以放入 export_magic.h 中,而 universal_header.h 变为:
In the dll source code you should have this implementation so that the .lib file exports the symbol:
The c client should use a header with this declaration so that the client code will import the symbol:
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:
Then the dll source code looks like this:
And the client looks like this:
If you do this a lot, the monster #ifdef at the top can go in export_magic.h and universal_header.h becomes:
当我在 Windows 中编程时,我从未使用过 _declspec(dllimport)。 您应该能够简单地声明
并链接到编译 DLL 时创建的 .libb。
I've never used _declspec(dllimport) when I was programming in Windows. You should be able to simply declare
and link to the .libb created when DLL was compiled.