繁体   English   中英

在 c# 代码中使用在 c++ dll 中定义的类

[英]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++ 类并使用 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM