如何从 C# 导入和使用非托管 C++ 类?

Posted

技术标签:

【中文标题】如何从 C# 导入和使用非托管 C++ 类?【英文标题】:How to import and use a unmanaged C++ class from C#? 【发布时间】:2011-01-18 11:53:05 【问题描述】:

我有一个本地 C++ dll、一些头文件和导入库。有没有办法在 C# 中实例化 dll 中定义的对象?

我知道的两种方式是:

    将 C++ 代码包装到 COM 中 使用 DLLImport 和外部 C 函数

【问题讨论】:

您的 C++ 代码是否依赖于任何其他库,例如 boost? 是的。 FLOPC++(但它不是我的 C++ 代码)。 【参考方案1】:

C++/CLI 是你的朋友。不过,您会遇到一个问题:无法将标准 C++ 对象存储在 C++/CLI 引用或值类(.NET 的类)中。所以你必须求助于我在生产代码中使用的以下类(你可以修改):

#pragma once
#include <boost/shared_ptr.hpp>

template <typename T>
ref class Handle

    boost::shared_ptr<T>* t;

    !Handle() 
    
        if (t != nullptr)
        
            delete t;
            t = nullptr;
        
    

    ~Handle()  this->!Handle(); 

public:
    Handle() : t(new boost::shared_ptr<T>((T*)0)) 

    Handle% operator=(T* p)
    
        if (p != t->get()) t->reset(p);
        return *this;
    

    static T* operator&(Handle% h)  return h.t->get(); 
    static boost::shared_ptr<T> operator->(Handle% h)  return *h.t; 

    T& reference()  return *t->get(); 
    T const& const_reference()  return *t->get(); 
;

用法:Handle&lt;MyCppClass&gt;^ handle; 在 C++/CLI 类中。然后实现存根方法,将它们转发给handle 成员。如果没有更多指向它的指针,垃圾收集对象将调用 C++ 类实例的析构函数:

public ref class Foo

    void bar()  handle->bar(); 

internal:
    Handle<CppNamespace::Foo>^ handle;
;

【讨论】:

为了更好地理解:这是一个用 C++/CLI 编写的通用包装器。它管理内存处理。如果我想从 C# 访问本机 C++,那么我必须访问/编写自己的 C++/CLI 代码(包括此类)。然后此代码访问本机 C++。这是正确的吗? 是的。这在 .NET 资源的非确定性语义和 C++ 析构函数的确定性之间架起了一座桥梁。相反(在本机 C++ 类中具有 .NET 类型),请使用 cli::gcroot 类模板。您可能还想在 cli::pin_ptr 类模板上记录。【参考方案2】:

我认为您的选择只是构建一个 C++/CLI 类包装器(因此您可以像引用 c# 类一样引用它),否则您无法从 c# 代码实例化 c++ 类(非托管)。

替代方法可能是“丑陋”的方式:通过 c 函数实例化 c++ 类,但您会将该类视为 c# 代码中的 void 指针,因此您基本上不会对它做任何事情(除非您创建与此类交互的其他函数;仅限 C 函数)

C# 理解 C,如果你想让它理解 C++,你必须使用 C++/CLI

附: C# 对 C++ 类有一些基本的了解,但它只是将类数据(我的意思是字节:字段)转换为 C# 中的一些可用数据(有一些属性),但不允许使用方法和类似的东西(避免完全是我的建议)。

【讨论】:

这是一个选项,但不是他唯一的选项。 COM 路由可能更容易(或至少更直接)实现。 C# 可以使用 Interop 层轻松访问 COM 对象。 确实,我认为 COM 选项(和静态 C 函数调用)更容易。特别是:1. 如果您以前从未使用过 C++/CLI(像我一样)和 2. 因为 dll 的作者必须实现它们而不是我(在我的情况下)

以上是关于如何从 C# 导入和使用非托管 C++ 类?的主要内容,如果未能解决你的问题,请参考以下文章

C# 中的非托管 C++ 类

C# 使用 CLI 包装器调用非托管 C++

C# 托管非托管代码

从 C# 线程调用非托管代码

编写用于 C# 的非托管 C++ DLL

在 C++ 非托管应用程序中使用 C# 托管应用程序类