Здравствуйте, Евгений Музыченко, Вы писали:
ЕМ>У меня в одном из проектов на MS VC++ есть интерфейсная DLL с парой классов и несколькими глобальными функциями. Всего функций около пары десятков. Все крайне примитивно, используется только WinAPI и простейшие функции CRT, исключения не бросаются и не обрабатываются.
ЕМ>Заказчик хочет вызывать функции этой DLL из C#, но совершенно не разбирается в том, как дружить C# с C++, а я, соответственно, ничего не знаю про внутреннюю организацию C#, и некогда в нее глубоко лезть. Пока сошлись на том, что я добавлю в DLL обертки в стиле WinAPI, а они у себя сделают обертки для них.
Есть несколко способов использовать C++ Dll в C# проекте:
1) P/Invoke
В Dll экспортируете все функции через C интерфейс и в C# проекте через DllImport используете эти функции.
Это в принципе , то что вы собираетесь делать. Неудобство здесь в том, как мне кажется, что если есть готовые классы в Dll, то их надо заворачивать в "обёртку".
2) C++/CLI
Использовать Managed C++ от Microsoft.
Здесь интерфейс пишится на стороне C# проекта. С++ классы пакуются в С++/CLI классы, С++/CLI классы используются в C# классах.
Плюсы: Можно использовать С++ классы напрямую из Dll.
Минусы: Свой специфический синтаксис C++/CLI.
3) Через СОМ интерфейс
Здесь ничего сказать не могу, не использовали.
Re[6]: Как проще подключить C++ DLL к приложению на C#?
ЕМ>В C# все действительно настолько просто в плане интерфейса со статическими функциями в стиле C? Тогда очень странно, что мои заказчики за прошедшие полтора месяца так и не осилили вызов части функций-переходников, которые я им сделал, и просят сделать поверх них еще и агрегаторы с параметрами по умолчанию.
Ну да, все именно настолько просто
Тут скорее вопрос к чему привык. Такой "интерфейс" кажется простым если было суровое детство и деревянные игрушки
bnk>>Функции WinAPI из C# вызываются без проблем.
ЕМ>То есть, при появлении в WinAPI новых функций, достаточно описать их прототипы в C#, и сразу вызывать? Ждать, пока обновятся интерфейсные библиотеки для .NET или C#, не нужно?
Ну да, так и есть.
Re[4]: Как проще подключить C++ DLL к приложению на C#?
Здравствуйте, Евгений Музыченко, Вы писали:
ЕМ>Я, при здравом размышлении, решил пока ограничиться набором статических сишных оберток. Этот заказчик, что хочет вызывать мои API из C#, сам по себе какой-то мутный, и не факт, что в обозримое время появится еще кто-то на C#. С C++/CLI я до сих пор дела не имел — пришлось бы в нем разбираться, а если что-то не так заработает в связке, то разбираться придется еще и в том, насколько правильно я экспортирую классы/методы. Заказчик мне в этом вряд ли поможет — насколько я понимаю, они используют C# на уровне "написали, как в документации — заработало, как ожидали". А при экспорте простых оберток я, по крайней мере, могу оценить правильность экспорта и по .map, и по PE, и быстро протестировать DLL своими силами.
Мы так годами и делаем. Существенный плюс, что можно ещё на С++ писать тесты для своих экспортируемых функций и быть уверенным, что они работают.
Re: Как проще подключить C++ DLL к приложению на C#?
У меня в одном из проектов на MS VC++ есть интерфейсная DLL с парой классов и несколькими глобальными функциями. Всего функций около пары десятков. Все крайне примитивно, используется только WinAPI и простейшие функции CRT, исключения не бросаются и не обрабатываются.
Заказчик хочет вызывать функции этой DLL из C#, но совершенно не разбирается в том, как дружить C# с C++, а я, соответственно, ничего не знаю про внутреннюю организацию C#, и некогда в нее глубоко лезть. Пока сошлись на том, что я добавлю в DLL обертки в стиле WinAPI, а они у себя сделают обертки для них.
Будет ли оптимальным способом разворачивать классы в наборы глобальных функций типа Class1_Func1, Class1_Func2 и т.д., добавляя первым параметром указатель на объект, или есть более изящный способ оформить в C# классы такой же структуры, и вызывать функции по-человечески? Например, добавить к классам абстрактные интерфейсы, сделав все функции виртуальными, оформить эти классы в стиле COM, или еще как.
Здравствуйте, Евгений Музыченко, Вы писали:
ЕМ>Будет ли оптимальным способом разворачивать классы в наборы глобальных функций типа Class1_Func1, Class1_Func2 и т.д., добавляя первым параметром указатель на объект,
Я бы так и сделал. Более того, я уже так пару раз интерфейсы своих плюсовых объектов оформлял для наших шарпистов. Интерфейсы не слишком развесистые, поэтому всё ручками делал. Шарписты, в свою очередь, импортировали эти функции из DLL, и оформляли в свой класс. Там тоже всё просто (но я деталей не помню)
ЕМ>Например, добавить к классам абстрактные интерфейсы, сделав все функции виртуальными, оформить эти классы в стиле COM, или еще как.
Можно, но это лишний гемор на ровном месте, имхо. Если, конечно, каких-то дальнейших перспектив нет
Re[2]: Как проще подключить C++ DLL к приложению на C#?
Здравствуйте, удусекшл, Вы писали:
ЕМ>>Например, добавить к классам абстрактные интерфейсы, сделав все функции виртуальными, оформить эти классы в стиле COM, или еще как.
У>Можно, но это лишний гемор на ровном месте, имхо. Если, конечно, каких-то дальнейших перспектив нет
Перспективы есть, но весьма скромные — может, еще пять-десять функций добавится за год-два. Это просто интерфейсная DLL для общения приложения с драйвером. Понятно, что технически проще развернуть классы в глобальные функции, но очень уж это уродливо.
Re: Как проще подключить C++ DLL к приложению на C#?
Здравствуйте, Евгений Музыченко, Вы писали:
ЕМ>У меня в одном из проектов на MS VC++ есть интерфейсная DLL с парой классов и несколькими глобальными функциями. Всего функций около пары десятков. Все крайне примитивно, используется только WinAPI и простейшие функции CRT, исключения не бросаются и не обрабатываются.
ЕМ>Перспективы есть, но весьма скромные — может, еще пять-десять функций добавится за год-два. Это просто интерфейсная DLL для общения приложения с драйвером. Понятно, что технически проще развернуть классы в глобальные функции, но очень уж это уродливо.
Да вы, батенька, эстет
Re[3]: Как проще подключить C++ DLL к приложению на C#?
Здравствуйте, Евгений Музыченко, Вы писали:
ЕМ>Перспективы есть, но весьма скромные — может, еще пять-десять функций добавится за год-два. Это просто интерфейсная DLL для общения приложения с драйвером. Понятно, что технически проще развернуть классы в глобальные функции, но очень уж это уродливо.
Я бы обернул в COM. В С# тогда они получат авто-комплит как минимум и контекстный хелп как максимум (если только для винды)
Также тогда твою DLL можно будет автоматом использовать из всяких VBA (офиса) и питона например.
Проще всего делается через ATL, но можно и все руками.
Работы (для тебя) будет на порядок больше чем экспортировать голые функции.
Если все же экспортировать голые функции, то (им?) еще придется писать их определения на C# для вызова через P-Invoke. Не задолбают вопросами?
Я понимаю что проблемы индейцев шерифа не волнуют, но когда автокомплит есть, это все же лучше, чем когда его нет.
А вообще "леопольд, выходи" из пещеры, мир изменился
Re[2]: Как проще подключить C++ DLL к приложению на C#?
Здравствуйте, ArtDenis, Вы писали:
AD>beautiful-capi или аналог
Да там немного, меня и руками не заломает, а оберток для C# там все равно нет. Вопрос в том, есть ли относительно простой способ вызывать из C# элементарные методы классов C++ без раскидывания их по глобальным функциям.
Re[4]: Как проще подключить C++ DLL к приложению на C#?
Здравствуйте, bnk, Вы писали:
bnk>Проще всего делается через ATL, но можно и все руками.
Регистрировать в каталоге COM-серверов нужно, или из C# можно дергать DLL напрямую через DllGetClassObject?
bnk>Если все же экспортировать голые функции, то (им?) еще придется писать их определения на C# для вызова через P-Invoke. Не задолбают вопросами?
Они задолбают в любом случае (практически уже).
bnk>А вообще "леопольд, выходи" из пещеры, мир изменился
Что в свете этого следует сделать?
Re[3]: Как проще подключить C++ DLL к приложению на C#?
Здравствуйте, Евгений Музыченко, Вы писали:
AD>>beautiful-capi или аналог
ЕМ>Вопрос в том, есть ли относительно простой способ вызывать из C# элементарные методы классов C++ без раскидывания их по глобальным функциям.
Нет.
PS: Почему по глобальным-то? Правильно: по функциям, которые представляют API к классам в плоском виде. beautiful-capi сгенерирует такие функции, экспортирует из и напишет ООП-объёртку на указанном языке. Ручками это тоже сделать можно, но нужно ли?
Здравствуйте, Евгений Музыченко, Вы писали:
ЕМ>Да там немного, меня и руками не заломает, а оберток для C# там все равно нет. Вопрос в том, есть ли относительно простой способ вызывать из C# элементарные методы классов C++ без раскидывания их по глобальным функциям.
Есть (скорее был) C++/CLI (попытка микрософта упростить твою задачу), но сейчас пациент AFAIK скорее мертв, чем жив. Используй COM/ATL. Ленина может даже раньше закопают, чем его.
Re[5]: Как проще подключить C++ DLL к приложению на C#?
Здравствуйте, Евгений Музыченко, Вы писали:
ЕМ>Регистрировать в каталоге COM-серверов нужно, или из C# можно дергать DLL напрямую через DllGetClassObject?
Регистрировать не обязательно, есть т.н. "registration-free" вариант (в manifest файле), который достаточно положить рядом с DLL. https://docs.microsoft.com/en-us/dotnet/framework/interop/registration-free-com-interop
bnk>>А вообще "леопольд, выходи" из пещеры, мир изменился
ЕМ>Что в свете этого следует сделать?
Как минимум написать Hello World на C#
я приводил пример,от COMа там подсчет ссылок да реализация QueryInterface, этого достаточно для взаимодействия с .NET.
Не критики ради, а справедливости для, если так сделать, то мне кажется автокомплит не будет работать (библиотека типов не сгенерируется?). К тому же джентельмены руками QueryInterface не пишут.
И нифига так не проще по сравнению с экспортом функций, там достаточно написать __declspec(dllexport) и фсё. Два слова.
Re[3]: Как проще подключить C++ DLL к приложению на C#?
Здравствуйте, bnk, Вы писали:
bnk>Не критики ради, а справедливости для, если так сделать, то мне кажется автокомплит не будет работать (библиотека типов не сгенерируется?).
Интерфейсы руками описываются на C# (с экспортом ф-й было бы также, только писанины больше), соотв. автокомплит будет родной шарповский, ессн никаих тайп-либов не будет. Это самая простая COM-реализация, которую можно дергать из .NET.
bnk>К тому же джентельмены руками QueryInterface не пишут.
Речь шла о нескольких классах, соотв. столько же будет и интерфейсов. А судя по постам ТС думаю он лишнее в код не будет тянуть и прикручивать ATL.
bnk>И нифига так не проще по сравнению с экспортом функций, там достаточно написать __declspec(dllexport) и фсё. Два слова.
и фсё? Ну как минимум с десяток экспортов функций (судя по 1-му посту ТС), которые надо написать и в которых будет перенаправление вызова к методам классов. На создание интерфейсов из существующих классов уйдет куда меньше времени.
Если бы речь шла о кроссплатформе, то тут да — экспорт функций был бы более универсальным.
Вопрос ТС — как сделать проще, имхо проще и быстрее как я описал (ссылка на пример в посте выше).
ps: кстати если порыться в топике на который я сослался, тут
я попробовал https://github.com/mono/CppSharp , который по заголовочному файлу умеет генерить обертку на C# (порой кривовато, мож уже починили), но в целом работающая штука.
Re[4]: Как проще подключить C++ DLL к приложению на C#?
Здравствуйте, pilgrim_, Вы писали:
bnk>>Не критики ради, а справедливости для, если так сделать, то мне кажется автокомплит не будет работать (библиотека типов не сгенерируется?).
_>Интерфейсы руками описываются на C# (с экспортом ф-й было бы также, только писанины больше)
Другими словами — автокомплита из коробки не будет. Что я и сказал собственно.
bnk>>И нифига так не проще по сравнению с экспортом функций, там достаточно написать __declspec(dllexport) и фсё. Два слова.
_>Вопрос ТС — как сделать проще, имхо проще и быстрее как я описал (ссылка на пример в посте выше).
Самое простое — написать перед каждой экспортируемой функцией __declspec(dllexport) и задекларировать ее в C# для вызова через P-Invoke (две строчки)
Текста будет на порядок меньше чем с ATL/COM. Но и юзабилити этого на уровне пещерных людей. Типа так:
Если использовать ATL, то 90% кода можно "написать" с помощью визарда в студии, как поступают джентельмены.
New => Atl Project, New => Simple Object, потом просто добавить к нему методы и реализации. фсё.
Но это в десятки раз больше неочевидного кода, и просто горы синтаксического оверхеда.
Зато потом даже обезьяна сможет добавить эту библиотеку к проекту на C# кликнув мышкой на "Add Reference", и получит полный фарш с автокомплитом.
Что собственно ожидают от библиотеки нормальные люди.
Лебедю, чтобы грациозно плавать, приходится очень быстро махать лапами под водой, ничего здесь не поделаешь
Еще альтернатива — сделать промежуточную DLL-обертку на C#, в которой написать все эти корявые DllImport самому. Из которой экспортировать для C# красивые классы с методами.
Но тогда будет две DLL. Можно обернуть это в nuget пакет и опубликовать в публичном репозитории для удобства, чтобы простота использования оставалась на уровне обезьяны.
Кстати, еще один вариант — тупо переписать эту DLL написанную на C++, на C#, если она небольшая.
Функции WinAPI из C# вызываются без проблем.
Плюсую за этот вариант, несколько раз пользовался. Преимущества перед классическим pinvoke:
все описания в одном месте, нет необходимости "не забыть поправить C#" если изменил контракт на сишной стороне
гораздо прозрачнее менеджмент памяти: CLI поддерживает как managed-пулы памяти, так и native, делаем на стыке двух миров все необходимые преобразования и отпускаем память если больше не надо
енумы — опять же, см. пункт 1, описываем в одном месте (С++) и CLI выставит его на дотнетную часть, главное в отдельный namespace не забыть обернуть — иначе не увидит, global namespace оно не экспортирует
все проверки — compile time
Re[3]: Как проще подключить C++ DLL к приложению на C#?
Здравствуйте, Mr.Delphist, Вы писали:
AS>>С++ dll --> C++/CLI dll --> C# dll
MD>Плюсую за этот вариант, несколько раз пользовался. Преимущества перед классическим pinvoke:
Я, при здравом размышлении, решил пока ограничиться набором статических сишных оберток. Этот заказчик, что хочет вызывать мои API из C#, сам по себе какой-то мутный, и не факт, что в обозримое время появится еще кто-то на C#. С C++/CLI я до сих пор дела не имел — пришлось бы в нем разбираться, а если что-то не так заработает в связке, то разбираться придется еще и в том, насколько правильно я экспортирую классы/методы. Заказчик мне в этом вряд ли поможет — насколько я понимаю, они используют C# на уровне "написали, как в документации — заработало, как ожидали". А при экспорте простых оберток я, по крайней мере, могу оценить правильность экспорта и по .map, и по PE, и быстро протестировать DLL своими силами.
Re: Как проще подключить C++ DLL к приложению на C#?
Тут необходимо ответить на ряд вопросов прежде чем выбирать решение.
Насколько нужна будет в будущем кроссплатформенность.
COM у нас только в Windows.
Если это не проблема, то самый удобный вариант.
Описываются интерфейсы в IDL далее создаём TLB из которой создаётся DLL .NET assembly и получаем подсказки и автодополнения.
Единственный недостаток это то, что если опыта в этом нет, придётся немного повозиться.
Зато любые будущие изменения делаются легко и непринуждённо.
Ну и как указали выше это даёт возможность вызывать код из других языков как VBScript если маршалить через oleautomation.
Насколько нужен ли .NET Core и какой версии.
До недавнего времени там не было поддержки C++/CLI.
Самый стабильный вариант это простой C++ и C#.
Приходится дважды описывать функции, зато никаких проблем когда C++/CLI вдруг перестанет работать.
У C++/CLI нет поддержки мульти-таргетинга то бишь компиляции под разные версии фреймворков как есть у C#.
Возможно это не создаёт проблему сейчас, но вот у нас из-за этого была проблема и невозможность перейти на новый компилятор C++.
В C# все действительно настолько просто в плане интерфейса со статическими функциями в стиле C? Тогда очень странно, что мои заказчики за прошедшие полтора месяца так и не осилили вызов части функций-переходников, которые я им сделал, и просят сделать поверх них еще и агрегаторы с параметрами по умолчанию.
bnk>Функции WinAPI из C# вызываются без проблем.
То есть, при появлении в WinAPI новых функций, достаточно описать их прототипы в C#, и сразу вызывать? Ждать, пока обновятся интерфейсные библиотеки для .NET или C#, не нужно?
Re[7]: Как проще подключить C++ DLL к приложению на C#?
Здравствуйте, Евгений Музыченко, Вы писали:
ЕМ>У меня в одном из проектов на MS VC++ есть интерфейсная DLL с парой классов и несколькими глобальными функциями. Всего функций около пары десятков. Все крайне примитивно, используется только WinAPI и простейшие функции CRT, исключения не бросаются и не обрабатываются.
ЕМ>Заказчик хочет вызывать функции этой DLL из C#, но совершенно не разбирается в том, как дружить C# с C++, а я, соответственно, ничего не знаю про внутреннюю организацию C#, и некогда в нее глубоко лезть. Пока сошлись на том, что я добавлю в DLL обертки в стиле WinAPI, а они у себя сделают обертки для них.
ЕМ>Будет ли оптимальным способом разворачивать классы в наборы глобальных функций типа Class1_Func1, Class1_Func2 и т.д., добавляя первым параметром указатель на объект, или есть более изящный способ оформить в C# классы такой же структуры, и вызывать функции по-человечески? Например, добавить к классам абстрактные интерфейсы, сделав все функции виртуальными, оформить эти классы в стиле COM, или еще как.
Лучший вариант для малого количества Pinvoke
c++ часть
extern "C" __declspec(dllexport) bool Function(SomeClass * ptr,const wchar* descr,uint16_t & param)
{
Плюсы- можно сделать загрузку библиотек разной разрядности если надо x86, переносимо между платформами.
Минусы- описание функциий в двух местах, бустолковая работа с указателями даже на примитивные типы
Другие варианты:
COM-лучше развидеть и забыть, windows-only и коряв. Если близко не знаком, то и не стоит связываться.
C++/CLR- вырвиглазный синтаксис от которого у здорового человека умеющего в С++ и C# начинаеться нервный тик, странные глюки при инициализации с шаманством, .NET 5 вроде поддерживаеться, но не факт что нормально работает. Пригодиться скорее наоборот, для вызова .NET из нативной программы.
Re: Как проще подключить C++ DLL к приложению на C#?
Здравствуйте, Евгений Музыченко, Вы писали:
ЕМ>Заказчик хочет вызывать функции этой DLL из C#, но совершенно не разбирается в том, как дружить C# с C++, а я, соответственно, ничего не знаю про внутреннюю организацию C#, и некогда в нее глубоко лезть. Пока сошлись на том, что я добавлю в DLL обертки в стиле WinAPI, а они у себя сделают обертки для них.
В С# для этого есть встроенная возможность с unmanаged code и стадо примеров в MSDN и инете.
Когда лет 15 назад мне понадобилась и за день разобрался и сделал(C# не знал, не знаю и знать не хочу).