Создайте неуправляемый объект С++ в С#

У меня есть неуправляемая dll с классом MyClass. Теперь есть способ создать экземпляр этого класса в коде С#? Вызов его конструктора? Я попытался, но визуальная студия сообщила об ошибке с сообщением о том, что эта область памяти повреждена или что-то в этом роде.

Заранее спасибо

Ответ 1

С# не может создать экземпляр класса, экспортированного из родной Dll. У вас есть два варианта:

  • Создайте оболочку С++/CLI. Это библиотека классов .NET, которая может быть добавлена ​​как ссылка на любой другой проект .NET. Внутренний класс С++/CLI работает с неуправляемым классом, привязывая к родной Dll стандартными правилами С++. Для .NET-клиента этот класс С++/CLI выглядит как класс .NET.

  • Write C wrapper для класса С++, который может использоваться клиентом .NET с PInvoke. Например, чрезмерно упрощенный класс С++:

    class MyClass()
    {
    public:
        MyClass(int n){data=n;}
        ~MyClass(){}
        int GetData(){return data;}
    private:
        int data;
    };

C API-оболочка для этого класса:

    void* CreateInstance()
    {
        MyClass* p = new MyClass();
        return p;
    }

    void ReleaseInstance(void* pInstance)
    {
        MyClass* p = (MyClass*)pInstance;
        delete p;
    }

    int GetData(void* pInstance)
    {
        MyClass* p = (MyClass*)pInstance;
        return p->GetData();
    }

    // Write wrapper function for every MyClass public method.
    // First parameter of every wrapper function should be class instance.

CreateInstance, ReleaseInstance и GetData могут быть объявлены в клиенте С# с использованием PInvoke и вызваны напрямую. Параметр void * должен быть объявлен как IntPtr в объявлении PInvoke.

Ответ 2

Вы не можете использовать код С++ без изменений непосредственно на С#. Взаимодействие можно выполнить с помощью PInvoke. Есть много проблем, связанных с этим темой, особенно при вызове функций, которые имеют указатели в качестве аргументов.

Основная процедура выполняется следующим образом:

С# часть

namespace MyNamespace {
  public class Test {
    [DllImport("TheNameOfThe.dll")]
    public static extern void CreateMyClassInstance();

    public void CallIt() {
        CreateMyClassInstance(); // calls the unmanged function via PInvoke
    }
  }
}

Часть С++

class MyClass {
  public: MyClass() { /** Constructor */ }
};

MyClass* staticObject;

extern "C" void CreateMyObjectInstance() {
   staticObject = new MyClass(); // constructor is called
} 

Ответ 3

Решение представляет собой оболочку С++/CLI, например:

#include "DllExportClass.h"

public ref class ManagedOperationHelper
{
    public:

    double Sum(double add1, double add2)
    {
        CDllExportClass obj;
        double ret=obj.Sum(add1, add2);
        return ret;
    }

    double Mult(double mult1, double mult2)
    {
        CDllExportClass obj;
        double ret=obj.Mult(mult1, mult2);
        return ret;
    }
};

где CDllExportClass - это класс, экспортированный из собственного кода. Выше находится .h С++/CLI. Позаботьтесь, чтобы найти lib для этой DLL. Поместите dll и lib в тот же каталог и скомпилируйте код С++/CLI. В каталоге управляемого кода поместите собственную dll и DLL С++/CLI. В управляемом проекте укажите ссылку на проект С++/CLI. Исключить в обработанном коде класс С++/CLI:

ManagedOperationHelper obj = new ManagedOperationHelper();
double ret=obj.Sum(10, 20);  

Все.