[英]using a class defined in a c++ dll in c# code
我有一個用 c++ 編寫的 dll,我需要在我的 c# 代碼中使用這個 dll。 搜索后我發現使用 P/Invoke 可以讓我訪問我需要的函數,但這些函數是在一個類中定義的,並使用非靜態私有成員變量。 所以我需要能夠創建這個類的一個實例來正確使用這些函數。 我怎樣才能訪問這個類以便我可以創建一個實例? 我一直無法找到一種方法來做到這一點。
我想我應該注意 c++ dll 不是我的代碼。
無法在 C# 代碼中直接使用 C++ 類。 您可以以間接方式使用 PInvoke 來訪問您的類型。
基本模式是為類 Foo 中的每個成員函數創建一個關聯的非成員函數,該函數調用該成員函數。
class Foo {
public:
int Bar();
};
extern "C" Foo* Foo_Create() { return new Foo(); }
extern "C" int Foo_Bar(Foo* pFoo) { return pFoo->Bar(); }
extern "C" void Foo_Delete(Foo* pFoo) { delete pFoo; }
現在是將這些方法 PInvoking 到您的 C# 代碼中的問題
[DllImport("Foo.dll")]
public static extern IntPtr Foo_Create();
[DllImport("Foo.dll")]
public static extern int Foo_Bar(IntPtr value);
[DllImport("Foo.dll")]
public static extern void Foo_Delete(IntPtr value);
缺點是你將有一個笨拙的 IntPtr 來傳遞,但圍繞這個指針創建一個 C# 包裝類來創建一個更有用的模型是一件有點簡單的事情。
即使您不擁有此代碼,您也可以創建另一個 DLL 來包裝原始 DLL 並提供一個小的 PInvoke 層。
C++ 代碼,ClassName.h
class __declspec(dllexport) CClassName
{
public:
CClassName();
~CClassName();
void function();
};
C++ 代碼,ClassName.cpp
CClassName::CClassName()
{
}
CClassName::~CClassName()
{
}
void CClassName::function()
{
std::cout << "Bla bla bla" << std::endl;
}
C++ 代碼,調用函數的 ClassNameCaller.h 文件
#include "ClassName.h"
#ifdef __cplusplus
extern "C" {
#endif
extern __declspec(dllexport) CClassName* CreateClassName();
extern __declspec(dllexport) void DisposeClassName(CClassName* a_pObject);
extern __declspec(dllexport) void function(CClassName* a_pObject);
#ifdef __cplusplus
}
#endif
C++ 代碼,調用函數的 ClassNameCaller.cpp 文件
#include "ClassNameCaller.h"
CClassName* CreateClassName()
{
return new CClassName();
}
void DisposeClassName(CClassName* a_pObject)
{
if(a_pObject!= NULL)
{
delete a_pObject;
a_pObject= NULL;
}
}
void function(CClassName* a_pObject)
{
if(a_pObject!= NULL)
{
a_pObject->function();
}
}
C# 代碼
[DllImport("ClassNameDll.dll")]
static public extern IntPtr CreateClassName();
[DllImport("ClassNameDll.dll")]
static public extern void DisposeClassName(IntPtr pClassNameObject);
[DllImport("ClassNameDll.dll")]
static public extern void CallFunction(IntPtr pClassNameObject);
//use the functions
IntPtr pClassName = CreateClassName();
CallFunction(pClassName);
DisposeClassName(pClassName);
pClassName = IntPtr.Zero;
以下是如何從 VB 調用 C++ 類方法的示例 - 對於 C#,您只需重寫步驟 4 中的示例程序。
您可能需要編寫一個中間 DLL(可能使用 C++)來為您處理此問題並公開您需要的接口。 您的 DLL 將負責加載第 3 方 DLL,創建此 C++ 對象的實例,並根據需要通過您設計的任何 API 公開其成員函數。 然后您將使用 P/Invoke 來獲取您的 API 並干凈地操作該對象。
注意:對於 DLL 的 API,嘗試將數據類型限制為基元(long、int、char* 等)以防止模塊邊界問題。
我這樣做的方法是在我的非托管 C++ DLL 周圍創建一個薄的托管 C++ 包裝器。 托管包裝器包含環繞非托管代碼的“代理”類,這些代碼公開 .NET 應用程序所需的接口。 這是一項雙重工作,但它允許在正常環境中進行相當無縫的操作。 在某些情況下(例如 ASP.NET)依賴項確實會變得更加棘手,但您可能不會遇到這種情況。
myfile.i
%module learnaboutswig
class A
{
public:
void boringfunction(char *charstr);
};
從swig.org下載swig
swig -c ++ -csharp myfile.i
查看輸出,看看它是否對您有用。
我同意 JaredPar。 在托管代碼中創建非托管類的實例應該是不可能的。
另一件事是 - 如果您可以在托管 C++ 中重新編譯 DLL 或從中制作一個 COM 組件,它會容易得多/
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.