Невозможно получить доступ к переменной в C++ DLL из приложения C.

StackOverflow https://stackoverflow.com/questions/56500

Вопрос

Я застрял на исправлении устаревшего приложения 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++ DLL была доступна из приложения C?


Ответ

Как определили Ботисмариус и другие (большое всем спасибо), мне нужно было связать с .lib библиотеки DLL.Чтобы предотвратить искажение имени, мне нужно было объявить его (в исходном коде C) без декораторов, а это значит, что мне нужно было использовать файл .lib.

Это было полезно?

Решение

вы должны связать его с библиотекой, созданной после компиляции DLL.В параметрах компоновщика проекта необходимо добавить .lib файл.И да, вам также следует объявить переменную как:

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

Другие советы

extern "C" - это то, как вы удаляете украшение - оно должно работать:

extern "C" declspec (dllimport) char MyNewVariable;

или если вам нужен заголовок, который может использоваться C++ или C (с переключателем /TC)

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

И, конечно же, ссылка на библиотеку импорта, созданную dll, выполняющей экспорт.

Я не уверен, кто понизил мод ботисмариуса, потому что он прав.Причина в том, что сгенерированный .lib — это библиотека импорта, которая позволяет легко просто объявить внешнюю переменную/функцию с помощью __declspec(dllimport) и просто используйте его.Библиотека импорта просто автоматизирует необходимые LoadLibrary() и GetProcAddress() звонки.Без этого вам придется вызывать их вручную.

Они оба правы.Тот факт, что сообщение об ошибке описывает __imp_?MyNewVariable@@3PADA означает, что он ищет украшенное имя, поэтому необходим внешний символ «C».Однако связывание с библиотекой импорта также необходимо, иначе вы просто получите другую ошибку ссылки.

@Грэм:В этом ты тоже прав.Я думаю, что компилятор «C», который использует OP, не обеспечивает соблюдение стандарта C99, а компилирует как C ++, тем самым искажая имена.Настоящий компилятор C не поймет часть «C» extern "C" ключевое слово.

в исходный код dll у вас должна быть эта реализация, чтобы файл .lib экспорт символ:

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

Клиент c должен использовать заголовок с этим объявлением, чтобы клиентский код Импортировать символ:

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

Этот заголовок вызовет ошибку компиляции, если #include-ed в исходном коде dll, поэтому он обычно помещается в заголовок экспорта, который используется только для экспортируемых функций и только клиентами.

Если вам нужно, вы также можете создать «универсальный» заголовок, который можно включить где угодно, и который будет выглядеть следующим образом:

#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 вверху может перейти в экспорт_магический.h и универсальный_header.h станет:

#include "export_magic.h"

EXPORTED char *MyNewVariable;

Я никогда не использовал _declspec(dllimport), когда программировал в Windows.Вы должны иметь возможность просто объявить

extern "C" char* MyNewVariable;

и ссылку на .libb, созданную при компиляции DLL.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top