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.
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.
来源:https://stackoverflow.com/questions/56500/cant-access-variable-in-c-dll-from-a-c-app