Таким образом, то, что я имею, является API C++, содержавшим в *.dll, и я хочу использовать приложение C# для вызова методов в API.
До сих пор я создал C++ / проект CLR, который включает собственный C++ API и управляемый для создания класса "моста", который немного походит на следующее:
// ManagedBridge.h
#include <CoreAPI.h>
using namespace __CORE_API;
namespace ManagedAPIWrapper
{
public ref class Bridge
{
public:
int bridge_test(void);
int bridge_test2(api_struct* temp);
}
}
.
// ManagedBridge.cpp
#include <ManagedBridge.h>
int Bridge::bridge_test(void)
{
return test();
}
int Bridge::bridge_test2(api_struct* temp)
{
return test2(temp);
}
У меня также есть приложение C#, которое имеет ссылку на C++ / CLR "Bridge.dll" и затем использует методы, содержавшие в. У меня есть много проблем с этим:
Править: Хорошо, таким образом, у меня есть основы, работающие теперь благодаря ответам ниже, однако моя структура (звоните, это "api_struct2" для этого примера) имеет и собственное перечисление и объединение в собственном коде C++, как следующее:
typedef struct
{
enum_type1 eEnumExample;
union
{
long lData;
int iData;
unsigned char ucArray[128];
char *cString;
void *pvoid;
} uData;
} api_struct2;
Я думаю, что выяснил, как получить перечислимую работу; я повторно объявил это в управляемом коде, и работаю "native_enum тест = static_cast (eEnumExample)" для переключения управляемой версии на собственный компонент.
Однако объединению озадачили меня, я не действительно уверен, как напасть на него.. Идеи кто-либо?
Да, вы передаете неуправляемую структуру по ссылке. Это проблема для программы на C #, указатели совершенно несовместимы со сборкой мусора. Не считая того факта, что в нем, вероятно, тоже нет объявления для структуры.
Вы можете решить эту проблему, объявив управляемую версию структуры:
public value struct managed_api_struct {
// Members...
};
Теперь вы можете объявить метод как
int bridge_test2(managed_api_struct temp); // pass by value
или
int bridge_test2(managed_api_struct% temp); // pass by reference
Выберите последнее, если структура имеет более 4 полей (~ 16 байтов). Метод должен скопировать элементы структуры по одному в неуправляемую api_struct и вызвать метод неуправляемого класса. К сожалению, это необходимо, поскольку структура памяти управляемой структуры непредсказуема.
Все это довольно механически, вам может помочь SWIG . Сам не использовал его, не уверен, достаточно ли он умен, чтобы справиться с принятой структурой.
Совершенно другой подход состоит в том, чтобы сделать класс-оболочку более чистым, предоставив ему конструктор и / или свойства, которые позволяют создавать содержимое api_struct. Или вы можете объявить класс ссылки-оболочки для структуры, как в управляемом коде.
, поскольку он не знает, что на самом деле представляет собой api_struct
Вам необходимо определить управляемую версию в сборке .NET, которая использует атрибуты (например, StructLayoutAttribute
), чтобы обеспечить правильную маршализацию.
Это кажется очень длинным [...]
Другой подход - создать COM-оболочку (например, с использованием ATL) вокруг вашего API. Это может потребовать больше усилий, но, по крайней мере, вы избежите двойного кодирования определений структур и функций, необходимых для P / Invoke.
Исправление : Вы создали проект C ++ / CLI: просто добавьте правильный '#pragma', чтобы сообщить компилятору, что это код .NET, и тогда на выходе будет сборка, на которую проект C # может просто ссылаться.
Юо пытается сделать этот способ более сложным, чем он есть на самом деле. Вам нужны две разные структуры. Один управляемый и один неуправляемый. Вы предоставляете управляемую версию извне (своему приложению C #). Это будет все ".Net-ish" без каких-либо концепций союзов или что-то в этом роде.
В своем мосту вы получаете управляемую версию структуры, вручную создаете неуправляемую структуру и пишете код для перемещения ваших данных, поле за полем, в неуправляемую структуру. Затем вызовите свой неуправляемый код и, наконец, переместите данные обратно в управляемую структуру.
Самое прекрасное в C ++ / CLI заключается в том, что управляемый код также может работать с неуправляемым кодом и данными (и включать неуправляемые файлы .h).