2017-04-13 53 views
0

這可能是由於缺乏C++/cli知識而導致的,但我似乎無法在任何地方找到此問題。將本地類添加到託管項目

我有一個名爲ManagedProject的項目,它使用/ CLR進行編譯,並且有一個名爲RefClass.cpp的(C++/cli)ref類和一個名爲CppClass.cpp的本機C++類。

我可以從RefClass調用CppClass的構造函數。

但是,我無法從另一個也使用/ clr編譯的項目「OtherProject」中調用CppClass。 OtherProject只有Other.cpp。 OtherProject有一個對ManagedProject的引用,所以我可以調用RefClass,但即使我能夠#include「CppClass.h」,當我嘗試調用CppClass的構造函數時,也會得到LNK2019和LNK2028錯誤。

從non/clr本機類中調用它時會出現相同的錯誤。


下面是一個代碼示例:

ManagedProject

RefClass.cpp:

// has a .h file with the constructor declaration & instance variable int test; 
#include "CppClass.cpp" 
RefClass:RefClass(int test){ 
    this->test = test; 
    CppClass inst(42); //This works 
} 

CppClass.cpp:

// has a .h file with the constructor declaration & instance variable int test2; 
CppClass:CppClass(int test2){ 
    this->test2 = test2; 
} 

OtherProject

Other.cpp:

#include "CppClass.cpp" 
int wmain(/*args*/){ 
    RefClass^ refinst = gcnew RefClass(64); //This works  
    CppClass inst(42); //This fails, I get LNK2019 & LNK2028 at Other.obj 
} 

實際的錯誤輸出: 注:此處SQLPrecheckReport是CppClass和appzsqlmigrate.cpp是Other.cpp,appzsqlmigrate是名OtherProject。

32> appzsqlmigrate.obj:錯誤LNK2028:無法解析的令牌(0A000B59) 「公共:__cdecl SQLPrecheckReport :: SQLPrecheckReport(INT)」 (?? 0SQLPrecheckReport @@ $$ FQEAA 3 H @ Z)中引用函數 「INT __cdecl wmain(INT,wchar_t的* *常量)」(wmain @@ $$ HYAHHQEAPEA_W @ Z?)

32> appzsqlmigrate.obj:錯誤LNK2028:無法解析的令牌(0A000B5A) 「公共:__cdecl SQLPrecheckReport (int,wchar_t * * const)「(?wmain @@ $$ HYAHHQEAP)中引用的」::〜SQLPrecheckReport(void)「 (?? 1SQLPrecheckReport @@ $$ FQEAA @ XZ) EA_W @ Z)

32> appzsqlmigrate.obj:錯誤LNK2019:解析外部符號 「公共:__cdecl SQLPrecheckReport :: SQLPrecheckReport(INT)」 (?? 0SQLPrecheckReport @@ $$ FQEAA 3 H @ Z)中引用函數 「INT __cdecl wmain(INT,wchar_t的* *常量)」(wmain @@ $$ HYAHHQEAPEA_W @ Z?)

32> appzsqlmigrate.obj:錯誤LNK2019:解析外部符號 「公共:__cdecl SQLPrecheckReport :: 〜SQLPrecheckReport(void)「 (??1SQLPrecheckReport @@ $$ FQEAA @ XZ)在函數引用爲 「int __cdecl wmain(INT,wchar_t的* *常量)」(?wmain @@ $$ HYAHHQEAPEA_W @ Z)

+1

CLR爲模塊提供了出色的支持,但它不會追溯地將該支持添加到非託管代碼中。你必須在這裏做普通的C++舞蹈,並把C++類放在一個普通的靜態庫或DLL項目中,並鏈接它們的.libs,以便可以共享本地代碼。 –

+0

@HansPassant,我現在看到這個問題不需要用C++/cli。很抱歉,如果這看起來很明顯,我完全不熟悉使用dll和庫。你能給我說明嗎?「把C++類放在一個普通的靜態庫或DLL項目中,並鏈接它們的.libs,以便可以共享本地代碼」?我迄今爲止所嘗試的解決方案沒有解決錯誤... –

回答

2

C++/CLI允許管理和非管理代碼共同生活在同一個DLL中,但它們仍然使用它們通常使用的鏈接機制。

託管代碼通過將託管類標記爲公共並將該程序集加載爲參考進行鏈接。非託管代碼通過在導出DLL中指定__declspec(dllexport)和在導入DLL/EXE中指定__declspec(dllimport)來導出函數。

如果您希望將其導出爲C++類,則需要根據錯誤消息爲#include "CppClass.h",它看起來像您已經在做的那樣。您需要指定那些declspec屬性;通常的做法是在項目設置中爲ManagedProject定義一個預處理器符號,但不適用於OtherProject,並將其鍵入#define __declspec(dllexport)__declspec(dllimport)

另一種方法是將非託管類包裝在託管類中,並使用.Net機制來處理鏈接。這將使鏈接變得更簡單,並且它非常適合C++/CLI的設計(儘管通常包裝將被C#使用,而不是更多的C++/CLI)。

+0

嗨大衛,我很感激幫助。 我不熟悉如何使用DLL(我仍然是新來的C + +和託管C + +)。我該如何執行此步驟:「在ManagedProject的項目設置中定義預處理器符號」? 理想情況下,我想使用CppClass作爲RefClass的包裝,這樣我就可以從非託管項目中使用RefClass。推薦的方法是什麼? –

+0

啊,你走向另一條路。我自己並沒有這樣做,但我的理解是,您可以查看如何從非託管應用程序調用託管代碼以加載.Net庫,並使用'gcroot'讓非託管類維護對託管對象的引用這是包裝。 –

相關問題