использование класса, определенного в библиотеке dll c++ в коде c#



У меня есть dll, которая была написана на c++, мне нужно использовать эту dll в моем коде c#. После поиска я обнаружил, что использование P/Invoke даст мне доступ к нужной мне функции, но эти функции определены в классе и используют нестатические частные переменные-члены. Поэтому мне нужно иметь возможность создать экземпляр этого класса, чтобы правильно использовать функции. Как я могу получить доступ к этому классу, чтобы создать экземпляр? Я не смог найти способ сделать это.



Я думаю, Я должен отметить, что dll c++ - это не мой код.

981   7  

7 ответов:

нет способа напрямую использовать класс C++ в коде C#. Вы можете использовать PInvoke косвенным образом для доступа к вашему типу.

основной шаблон заключается в том, что для каждой функции-члена в классе Foo создайте связанную функцию-не-член, которая вызывает функцию-член.

class Foo {
public:
  int Bar();
};
extern "C" Foo* Foo_Create() { return new Foo(); }
extern "C" int Foo_Bar(Foo* pFoo) { return pFoo->Bar(); }
extern "C" void Foo_Delete(Foo* pFoo) { delete pFoo; }

теперь это вопрос Пинвокинга этих методов в ваш код C#

[DllImport("Foo.dll")]
public static extern IntPtr Foo_Create();

[DllImport("Foo.dll")]
public static extern int Foo_Bar(IntPtr value);

[DllImport("Foo.dll")]
public static extern void Foo_Delete(IntPtr value);

недостатком является то, что у вас будет неудобный IntPtr для передачи, но это несколько просто создать класс-оболочку C# вокруг этого указателя, чтобы создать более удобную модель.

даже если у вас нет этого кода, Вы можете создать другую DLL, которая обертывает исходную DLL и предоставляет небольшой слой PInvoke.

Маршал C++ класс и использовать PInvoke

C++ Код, Имя Класса.h

class __declspec(dllexport) CClassName
{
 public:
    CClassName();
    ~CClassName();
    void function();

};

C++ Код, Имя Класса.cpp

CClassName::CClassName()
{
}

CClassName::~CClassName()
{
}

void CClassName::function()
{
    std::cout << "Bla bla bla" << std::endl;

}

C++ Код, ClassNameCaller.H файл для вызывающей функции

#include "ClassName.h"      

#ifdef __cplusplus
extern "C" {
#endif

extern __declspec(dllexport) CClassName* CreateClassName();

extern __declspec(dllexport) void DisposeClassName(CClassName* a_pObject);

extern __declspec(dllexport) void function(CClassName* a_pObject);


#ifdef __cplusplus
}
#endif

C++ Код, ClassNameCaller.cpp-файл для вызывающей функции

#include "ClassNameCaller.h"


CClassName* CreateClassName()
{
    return new CClassName();
}

void DisposeClassName(CClassName* a_pObject)
{
    if(a_pObject!= NULL)
    {
        delete a_pObject;
        a_pObject= NULL;
    }
}

void function(CClassName* a_pObject)
{
    if(a_pObject!= NULL)
    {
        a_pObject->function();
    }
}

C# код

[DllImport("ClassNameDll.dll")]
static public extern IntPtr CreateClassName();

[DllImport("ClassNameDll.dll")]
static public extern void DisposeClassName(IntPtr pClassNameObject);

[DllImport("ClassNameDll.dll")]
static public extern void CallFunction(IntPtr pClassNameObject);

//use the functions
IntPtr pClassName = CreateClassName();

CallFunction(pClassName);

DisposeClassName(pClassName);

pClassName = IntPtr.Zero; 

здесь это пример того, как вызвать метод класса C++ из VB - для C# вам нужно только переписать пример программы на шаге 4.

мой_файл.я

%module learnaboutswig

class A

{

public:

    void boringfunction(char *charstr);
};

скачать swig из swig.org

swig-c++ - csharp myfile.я

посмотрите на выход, посмотрите, будет ли он работать для вас.

возможно, вам потребуется написать промежуточную DLL (возможно, на C++), которая обрабатывает это для вас и предоставляет необходимый вам интерфейс. Ваша DLL будет отвечать за загрузку сторонней DLL, создание экземпляра этого объекта C++ и предоставление его функций-членов по мере необходимости через любой API, который вы разрабатываете. Затем вы будете использовать P / Invoke, чтобы добраться до вашего API и чисто манипулировать объектом.

Примечание: для API вашей DLL попробуйте ограничить типы данных примитивами (long, int, типа char* и т. д.) для предотвращения граничных проблем модуля.

Я согласен с JaredPar. Создание экземпляров неуправляемых классов в управляемом коде не должно быть возможно.

другое дело-если бы вы могли перекомпилировать DLL в управляемом C++ или сделать из него COM-компонент, это было бы намного проще/

Я сделал это, создав тонкую управляемую оболочку C++ вокруг моей неуправляемой библиотеки DLL C++. Управляемая оболочка содержит классы "прокси", которые обертывают неуправляемый код, предоставляя интерфейс, необходимый приложению .NET. Это немного двойная работа, но она позволяет довольно бесшовную работу в нормальных условиях. В некоторых случаях все становится сложнее с зависимостями (например, ASP.NET но вы, вероятно, не столкнетесь с этим.

Comments

    Ничего не найдено.