用于C ++类返回接口的C ++ / CLI包装器

时间:2014-09-03 17:20:01

标签: c# interface c++-cli

我正在寻找一种方法将C ++源代码库暴露给C#托管代码,以使代码重复尽可能小。主要问题是我需要适应的本机代码使用许多抽象类作为参数和返回值的接口。

例如:

class IXX
{
  virtual int DoIt() = 0;
}

class IFoo
{
  virtual int Foo(const IXX *) = 0;
}

class IBar
{
  virtual IFoo * Bar() = 0;
}

class A : IBar
{
  IFoo * Bar()
  {
    return new FooImpl();
  }
}

我发现的几乎所有样本都使用简单类型(例如intchar*等),而不是基于接口的复杂逻辑。作为可能的解决方案,所有C ++代码都可以用C ++ / CLI包装,但这意味着很多代码重复。

将此本机代码功能公开给C#的好方法是什么?

1 个答案:

答案 0 :(得分:2)

最好的解决方案可能是在C ++ / CLI中编写托管包装类,并使用C#中的包装类。非托管类不能在C#中使用。

您需要做的是复制所有类的公共接口,并让每个托管对象拥有它所包装的非托管对象。让所有方法调用非托管对象来完成它们的工作,并且任何对象结果都应该在包装器中返回。您还应该在此处理任何其他转化,例如std::stringSystem::String^,托管数组与指针&长度参数,那种类型的东西。

public interface class IXX
{
  int DoIt();
}

public interface class IFoo
{
  int Foo(IXX^ ixx);
}

public interface class IBar
{
  IFoo^ Bar();
}

public ref class A : IBar
{
private:
  Unmanaged:A* unmanagedA;

public:
  A()
  {
    // Create the unmanaged object that we're wrapping.
    this->unmanagedA = new Unmanaged:A();
  }

  A(Unmanaged:A* unmanagedA)
  {
    // Use the passed-in unmanaged object.
    this->unmanagedA = unmanagedA;
  }

  // Clean up the unmanaged object on Dispose (~A) and Finalize (!A).
  ~A() { delete this->unmanagedA; }
  !A() { delete this->unmanagedA; }

  IFoo^ Bar()
  {
    // First, get the result from the unmanaged object.
    Unmanaged::FooImpl* unmanagedFoo = this->unmanagedA->Bar();
    // Return it wrapped in a managed wrapper.
    return gcnew FooImpl(unmanagedFoo);
  }
}

// (Note: I didn't verify the correctness of this code with a compiler.)