我有一个用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并提供小型PInvoke层的DLL.
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;