.net — Как мне связаться с собственным классом в dll C ++ / Cli смешанного режима

У меня есть следующие настройки:

  • CSharp.dll, C # dll
  • CppCli.dll, смешанный режим C ++ / Cli dll.
  • Native.dll, родная C ++ dll.

Родной проект объявляет

class Native
{
public:
virtual void Add(int a);
};

который реализован в смешанном режиме проекта:

class Mixed : public Native
{
public:
virtual void Add(int a);
ICSharpInterface^ MakeManaged();
};

Поскольку базовый класс определен в Native, я могу передать свою реализацию другому коду на native. Но сейчас я хочу проверить этот класс.

Если я использую #pragma make_public(Mixed); это только сделает структуру общедоступной, без каких-либо функций, видимых извне.

Если я пытаюсь соединиться с dll смешанного режима из другой dll смешанного режима, я получаю ошибки компоновщика, потому что это собственный класс, и dll смешанного режима не генерирует .lib для ссылки.

И если я попытаюсь __declspec(dllexport) класс, Visual Studio жалуется, потому что интерфейс предоставляет управляемые вещи.

Итак, мой вопрос:

Как мне создать экземпляр этого класса в своих тестах? Я был бы рад любому решению, которое показывает, как создать экземпляр, где я могу вызвать его открытый интерфейс, независимо от того, из C ++, C ++ / Cli или из C #.

1

Решение

Вы пропустили важный шаг, вы еще не рассматривали, как нативная программа собирается создать экземпляр смешанный объект. Что нетривиально, требует загрузки и инициализации CLR, чтобы он мог выполнять управляемый код. Имейте в виду, что клиентский код не делает это автоматически, он не знает bean-компоненты о CLR, он знает только о Native.dll. Есть три основных способа сделать это:

  • Вы можете представить управляемые классы как объекты COM, что очень просто сделать с помощью атрибута [ComVisible]. Это можно сделать напрямую из C #, вам не нужна оболочка C ++ / CLI. Обычным недостатком является то, что клиентский код должен использовать COM для создания экземпляра объекта и выполнения вызовов для него, а не тот код, который программисты любят писать.
  • Вы можете разместить CLR самостоятельно, самое эффективное и гибкое решение. Эта журнальная статья дает представление, остерегайтесь того, что оно датировано.
  • Компилятор C ++ / CLI дает вам возможность предоставить вам неуправляемую экспортируемую функцию, которая может выполнять управляемый код. Он автоматически генерирует заглушку, которая при необходимости загружает и инициализирует CLR.

Сфокусируясь немного на последнем пункте, так как это то, что вам, вероятно, нравится, здесь вам нужно заводская функция, тот, который создает экземпляр смешанный class и возвращает Native * обратно вызывающей стороне. Так что он может вызвать ptr-> Add () и вызвать Mixed :: Add (). Это может выглядеть так:

extern "C" __declspec(dllexport)
Native* CreateObject() {
return new Mixed;
}

Также получает импорт .lib, который вы можете связать в своем родном проекте. Остерегайтесь недостатков, они значительны. Это не совсем быстро, так как заглушка должна проверить, инициализирована ли CLR, и выполнить переход от нативного к управляемому. Отчеты об ошибках чрезвычайно отвратительны, поскольку у вас нет приличного способа диагностировать исключения, которые генерируются в коде C #. А управление памятью является проблемой, вызывающая сторона должна быть в состоянии успешно уничтожить возвращенный объект, который требует, чтобы все модули использовали один и тот же CRT. Вид проблем, которые COM решает.

Точно такая же техника доступна и в C # с использованием переписывающего устройства IL. Gieseke-х неуправляемый экспорт Шаблон популярен.

3

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]