Представление API C++ к C#

Таким образом, то, что я имею, является 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" и затем использует методы, содержавшие в. У меня есть много проблем с этим:

  1. Я не могу выяснить, как назвать bridge_test2 в рамках программы C#, поскольку это не знает о том, каков api_struct на самом деле. Я знаю, что должен упорядочить объект где-нибудь, но я делаю это в программе C# или C++ / мост CLR?
  2. Это походит на очень многоречивый способ выставить все методы в API, есть ли не более легкий способ, которым я пропускаю? (Который не использует P/Invoke!)

Править: Хорошо, таким образом, у меня есть основы, работающие теперь благодаря ответам ниже, однако моя структура (звоните, это "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)" для переключения управляемой версии на собственный компонент.

Однако объединению озадачили меня, я не действительно уверен, как напасть на него.. Идеи кто-либо?

7
задан Siyfion 12 April 2010 в 15:54
поделиться

3 ответа

Да, вы передаете неуправляемую структуру по ссылке. Это проблема для программы на 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. Или вы можете объявить класс ссылки-оболочки для структуры, как в управляемом коде.

3
ответ дан 7 December 2019 в 07:42
поделиться

, поскольку он не знает, что на самом деле представляет собой api_struct

Вам необходимо определить управляемую версию в сборке .NET, которая использует атрибуты (например, StructLayoutAttribute ), чтобы обеспечить правильную маршализацию.

Это кажется очень длинным [...]

Другой подход - создать COM-оболочку (например, с использованием ATL) вокруг вашего API. Это может потребовать больше усилий, но, по крайней мере, вы избежите двойного кодирования определений структур и функций, необходимых для P / Invoke.

Исправление : Вы создали проект C ++ / CLI: просто добавьте правильный '#pragma', чтобы сообщить компилятору, что это код .NET, и тогда на выходе будет сборка, на которую проект C # может просто ссылаться.

2
ответ дан 7 December 2019 в 07:42
поделиться

Юо пытается сделать этот способ более сложным, чем он есть на самом деле. Вам нужны две разные структуры. Один управляемый и один неуправляемый. Вы предоставляете управляемую версию извне (своему приложению C #). Это будет все ".Net-ish" без каких-либо концепций союзов или что-то в этом роде.

В своем мосту вы получаете управляемую версию структуры, вручную создаете неуправляемую структуру и пишете код для перемещения ваших данных, поле за полем, в неуправляемую структуру. Затем вызовите свой неуправляемый код и, наконец, переместите данные обратно в управляемую структуру.

Самое прекрасное в C ++ / CLI заключается в том, что управляемый код также может работать с неуправляемым кодом и данными (и включать неуправляемые файлы .h).

2
ответ дан 7 December 2019 в 07:42
поделиться
Другие вопросы по тегам:

Похожие вопросы: