Can't access variable in C++ DLL from a C app

自作多情 提交于 2019-12-05 04:49:10
botismarius

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

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.

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.

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: 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.

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;

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.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!