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