使用 C++/CLI 公开 C++ 非托管代码 class 指向 C# 的指针

Exposing C++ unmanaged code class pointers to C# with C++/CLI

对于我对 C++/CLI 的非常基础的了解,我深表歉意,但它是最近才作为必需品介绍给我的。我正在尝试使用 C++/CLI 为非托管 C++ 库创建包装器。我已经关注 this helpful guide 并且可以确认它(以某种方式)起到了作用。我遇到的问题是 C++ 指针公开了对非托管库中 public classes 的访问。在我的 CPP 库中,我使用它们通过访问单个入口点 class 从多个 classes 调用方法。在 C# 中,我无法访问应该可以通过这些 class 指针访问的方法。我收到一条错误消息,指出“该成员由于其保护级别而无法访问”,并且“->”指针未授予对 exposed class 成员的访问权限。

我的代码如下所示:

UnmanagedCode::ClassA

...
// some code
...
public:
    void doSomething() { ... };
    ClassB* classB() { return classB.get(); };
private:
    std::unique_ptr<ClassB> classB_ {};

C++/CLI 包装器

public ref class WrapperClass: public ManagedObject<UnmanagedCode::ClassA>
{
public:
    WrapperClass() : ManagedObject(new UnmanagedCode::ClassA) {}; // template class code in the hyperlink
    ~WrapperClass() {};
    void doSomething() { m_Instance->doSomething(); };
    UnmanagedCode::ClassB* classB() { return m_Instance->classB(); };
};

C#程序

class Program
{
    static void Main(string[] args)
    {
        WrapperClass w = new WrapperClass();
        w.doSomething(); // this works fine
        w.classB(); // here is where I am getting the error
    }
}

我的C#知识,不如我的C++,仅供参考。 我不太明白你在这里做什么:

UnmanagedCode::ClassB* classB() { return m_Instance->classB(); };

此行 returns 指向您在 C# 中检索的 ClassB 对象的指针。据我所知,这将要求 ClassB 也是一个托管对象,否则,我认为您不能在不为不安全函数指针创建委托的情况下调用对象上的函数。

如果我理解你的问题是正确的,我认为像这样的东西可以解决你的问题,在 C++ 中:

void* classB() { return static_cast<void*>(m_Instance->classB()); };
void doSomethingWithClassB(void* instance) {static_cast<ClassB*>(instance)->doSomethingWithClassB();}

然后在 C# 中:

    class Program
    {
        static void Main(string[] args)
        {
            WrapperClass w = new WrapperClass();
            w.doSomething();
            unsafe
            {
                void* classb = w.classB();
                w.doSomethingWithClassB(classb);
            }
        }

我认为您需要为每个 class 提供一个包装器以使其在 c# 中有用。

即对于 return classB 你会写类似

MyClassBWrapper^ GetClassB(){ return gcnew MyClassBWrapper(m_Instance->classB());

虽然您可以在托管代码中随意使用指针,但它需要不安全的代码,而且使用起来非常麻烦。如果你正在编写一个 c++/cli 包装器,你应该提供一个完全托管的 API。除了(可选)对图像或类似的大数据块使用指针之外。