Определите интерфейс на C ++, который должен быть реализован на C # и C ++

StackOverflow https://stackoverflow.com/questions/64645

Вопрос

У меня есть интерфейс, который я определил на C ++, который теперь необходимо реализовать на C #.Каков наилучший способ сделать это?Я вообще не хочу использовать COM в своем определении интерфейса.Способ, которым я решил это прямо сейчас, заключается в том, чтобы иметь два определения интерфейса, одно на C ++ и одно на C #.Затем я предоставляю интерфейсы C # в качестве COM-сервера.Это было мое приложение, которое написано на C ++ и может вызывать C #.Могу ли я в любом случае избежать необходимости определять свою реализацию как на C ++, так и на C #?

Это было полезно?

Решение

Если вы готовы использовать C ++ / CLI для вашего управляемого кода вместо C #, то вы можете просто использовать собственное определение интерфейса C ++ непосредственно через заголовочный файл.Насколько легко это будет, будет зависеть от того, что именно есть в вашем интерфейсе - простейший случай - это то, что вы могли бы использовать из C.

Взгляните на Маркуса Хига Эксперт C ++/ CLI:.NET для программистов на Visual C ++, за много полезной информации о смешивании родного и управляемого C ++ в .NET.

Другие советы

Глоток это отличный инструмент для переноса классов C ++ на другие языки, такие как C #.

Почему вы не хотите использовать COM?

Это было бы моим предложением.COM-взаимодействие действительно хорошо работало для меня, и я использовал COM-объекты и интерфейсы в C # (просто ссылаюсь на COM-объект, и вызываемая во время выполнения оболочка создается автоматически).Аналогично, пометка класса C # как "Register для COM-взаимодействия" сработала наоборот.

Напишите интерфейс на C ++ и используйте макросы, чтобы сделать его похожим на стандартный заголовочный файл cpp в UNIX и на файл IDL в Windows (если это не сработает, вы всегда можете написать скрипт на python / ruby для генерации IDL из заголовочного файла C ++).

Скомпилируйте IDL для создания typelib.Используйте импортер TypeLib, чтобы сгенерировать определения интерфейса для C # и реализовать интерфейсы там.

Напишите интерфейс на IDL и используйте инструмент для компиляции интерфейса на целевой язык.Вы могли бы найти указания на это, изучив CORBA, который был связан с межъязыковым взаимодействием.

/Аллан

Другой подход заключается в использовании "плоского" API в стиле C.С таким же успехом вы могли бы использовать extern "C" для предотвращения случайной перегрузки.Используйте файл DEF для явного присвоения имен экспортируемым функциям, поэтому они определенно никак не оформлены (функции C ++ "оформлены" кодировкой типов параметров в таблице экспорта).

На x86 остерегайтесь соглашений о вызовах.Вероятно, это делается для того, чтобы явно заявить об использовании __stdcall или __cdecl.Поскольку P /Invoke в основном используется для вызова API-интерфейсов Windows, по умолчанию используется StdCall , но C и C ++ по умолчанию используют cdecl, поскольку это поддерживает varargs .

Недавно я обновил COM-интерфейс IRapiStream в плоском интерфейсе C, поскольку .NET, казалось, пытался преобразовать IStream в хранилище, что завершилось неудачей с ошибкой STG_E_UNIMPLEMENTEDFUNCTION.

Вы не упоминаете, какую версию .NET вы используете, но кое-что, что сработало для меня при использовании Visual Studio .NET 2003, - это предоставление тонкой оболочки C # вокруг упрощенной реализации реального класса C ++:

public __gc class MyClass_Net {
public:
   MyClass_Net()
      :native_ptr_(new MyClass())
   {
   }
   ~MyClass_Net()
   {
      delete native_ptr_;
   }

private:
   MyClass __nogc *native_ptr_;
};

Очевидно, что там было бы предпочтительнее использовать Boost shared_ptr, но я никогда не мог заставить их хорошо играть с V.NET 2003...

Методы просто перенаправляют к базовым методам C ++ через указатель.Возможно, придется преобразовать аргументы метода.Например, для вызова метода C ++, который принимает строку, метод C #, вероятно, должен принимать System.String (System::String в управляемом C ++).Для этого вам пришлось бы использовать System::Runtime::InteropServices::Marshal::StringToHGlobalAnsi() .

Одна приятная особенность этого подхода заключается в том, что, поскольку управляемый C ++ - это язык .NET, вы можете предоставлять средства доступа как свойства (__property).Вы даже можете выставлять атрибуты, очень похожие на C #.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top