簡體   English   中英

無法從C應用程序訪問C ++ DLL中的變量

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

我堅持修復傳統的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;

正如Tony所建議的(以及我之前嘗試過的)會產生不同的預期裝飾,但仍然沒有將其刪除:

未解析的外部符號__imp__MyNewVariable

如何編寫聲明,以便可以從C應用程序訪問C ++ DLL變量?


答案

由botismarius和其他人確認(非常感謝所有),我需要鏈接DLL的.lib。 為了防止名稱被破壞,我需要聲明它(在C源代碼中)沒有裝飾器,這意味着我需要使用.lib文件。

你必須鏈接編譯DLL后生成的lib。 在項目的鏈接器選項中,必須添加.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生成的導入庫鏈接。

我不確定是誰修改了botismarius,因為他是對的。 原因是.lib生成的是導入庫,可以很容易地使用__declspec(dllimport)簡單地聲明外部變量/函數並使用它。 導入庫只是自動執行必要的LoadLibrary()GetProcAddress()調用。 沒有它,您需要手動調用它們。

他們都是對的。 錯誤消息描述__imp_?MyNewVariable@@3PADA意味着它正在尋找裝飾名稱,因此extern“C”是必要的。 但是,鏈接到導入庫也是必要的,否則您將獲得不同的鏈接錯誤。

@Graeme:你也是對的。 我認為OP使用的“C”編譯器不是強制執行C99標准,而是編譯為C ++,因此會破壞名稱。 真正的C編譯器不會理解extern "C"關鍵字的“C”部分。

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;

我在Windows編程時從未使用_declspec(dllimport)。 你應該能夠簡單地宣布

extern "C" char* MyNewVariable;

並鏈接到編譯DLL時創建的.libb。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM