Маршаллинг класса C ++ как структура - PullRequest
1 голос
/ 28 января 2012

На стороне C ++ у меня есть следующее объявление класса:

class MyClass {
    ...fields
    MyClass();
    ~MyClass(); };

Этот класс используется в некоторых методах внутри dll.Он прошел и вернулся от них.Как я могу представить это в C #?Мне нужно сделать его полностью совместимым с C ++ dll.

Этот класс не имеет методов, определены только конструктор без параметров и деструктор.Есть идеи, как это сделать?К сожалению, я не могу использовать C ++ \ CLI, но я надеюсь, что это возможно сделать с C #.

У меня есть только одна идея - представить ее как структуру на стороне C # (у меня нет доступак коду C ++, к сожалению) и попробуйте Marshal.PtrToStructure.Но я не уверен, что это сработает.

Есть предложения?Спасибо.

1 Ответ

1 голос
/ 28 января 2012

Это не совсем возможно в C #. Он может отображать фрагменты данных между управляемым и собственным, но не поведением. Класс C ++ по своей природе обеспечивает поведение и, следовательно, не может быть упорядочен напрямую.

Однако вы можете сделать маршал IntPtr для нативного объекта и создать тонкий слой PInvoke, который просто использует IntPtr для доступа к фрагментам данных типа. Например, допустим, у меня был следующий класс C ++.

class MyClass {
public:
  int Field;
};

Я мог бы раскрыть его поведение с помощью следующего набора функций C.

extern "C" {

  void* MyClass_Create() {
    return new MyClass();
  }

  void MyClass_Delete(void* pValue) {
    delete reinterpret_cast<MyClass*>(pValue);
  }

  int MyClass_GetField(void* pValue) {
    return reinterpret_cast<MyClass*>(pValue)->Field;
  }

  void MyClass_SetField(void* pValue, int field) {
    reinterpret_cast<MyClass*>(pValue)->Field = field;
  }
}

Теперь, когда я раскрыл это через функции C, я могу создать тонкий управляемый упаковщик поверх него

internal static class NativeMethods {
  [DllImport("example.dll")]
  internal static extern IntPtr MyClass_Create();

  [DllImport("example.dll")]
  internal static extern void MyClass_Destroy(IntPtr ptr);

  [DllImport("example.dll")]
  internal static extern int MyClass_GetField(IntPtr prt);

  [DllImport("example.dll")]
  internal static extern void MyClass_SetField(IntPtr ptr, int field);
}


public class MyClass : IDisposable {
  private readonly IntPtr m_pointer;

  public int Field {
    get { return NativeMethods.MyClass_GetField(m_pointer); }
    set { NativeMethods.MyClass_SetField(m_pointer, value); }
  }

  public MyClass() {
    m_pointer = NativeMethods.MyClass_Create();
  }

  // Create from existing 
  public MyClass(IntPtr pointer) {
    m_pointer = pointer;
  }

  public void Dispose() {
    NativeMethods.MyClass_Destroy(m_pointer);
  }
}
...