Создать автоматическую оболочку C для библиотеки C ++?

Допустим, у меня есть C ++ DLL. AFAIK, не существует широко принятого стандарта ABI для C ++, поэтому, чтобы убедиться, что он работает и не зависит от компилятора целевого приложения, мне нужно было бы обернуть мою библиотеку в C-интерфейс.

Есть ли инструменты, которые могут автоматически генерировать такой интерфейс? Было бы также неплохо, если бы они могли генерировать оболочки вокруг интерфейса C, чтобы они выглядели так, как будто они являются исходными объектами C ++, например

Foo* f = new Foo();  // FooWrapper* fw = Foo_create();
f->bar("test");      // Foo_bar(fw, "test")

переводит в функции C, которые вызываются в моей библиотеке, используя сгенерированный C ABI. Я понимаю, что C ++ является довольно сложным языком, и не все может быть легко помещено в интерфейс C, но мне было интересно, есть ли такие решения, которые даже поддерживают подмножество языка C ++ (возможно, с помощью некоторого написанного вручную IDL / XML файлы)

3

Решение

не существует широко распространенного стандарта ABI для C ++

Я почти уверен, что это немного преувеличено — не так много разных компиляторов, доступных для какой-либо конкретной платформы, поэтому, вероятно, было бы проще просто создать DLL для каждого поставщика (например, Microsoft, GCC в Windows, GCC в Linux , Sun и GCC для Solaris, GCC для MacOS — насколько я знаю, CLANG совместим с GCC).

Добавить интерфейс уровня C в основном означает, что уровень интерфейса не должен:
1. Используйте любые объекты, которые требуют особого поведения копирования / назначения / построения.
2. Используйте любые «бросающие» исключения.
3. Используйте виртуальные функции.
через этот интерфейс.

По моему мнению, легче «исправить» проблемы, вызванные «отсутствием ABI», чем создать хороший интерфейс, подходящий для использования на C ++, с интерфейсом C в середине.

2

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

Если вы хотите, чтобы код C ++ вызывался из других компиляторов / стандартных библиотек, вы можете использовать cppcomponents из https://github.com/jbandela/cppcomponents. Полное раскрытие — я автор библиотеки.

Вот простой пример Привет мир

Сначала создайте файл с именем library.h
В этом файле вы определите компонент

#include <cppcomponents/cppcomponents.hpp>

struct IPerson
:public cppcomponents::define_interface<cppcomponents::uuid<0xc618fd04,0xaa62,0x46e0,0xaeb8,0x6605eb4a1e64>>
{

std::string SayHello();

CPPCOMPONENTS_CONSTRUCT(IPerson,SayHello);};

inline std::string PersonId(){return "library!Person";}

typedef cppcomponents::runtime_class<PersonId,cppcomponents::object_interfaces<IPerson>> Person_t;
typedef cppcomponents::use_runtime_class<Person_t> Person;

Далее создайте library.cpp
В этом файле вы будете реализовывать интерфейс и компонент

#include "library.h"
struct PersonImplementation:cppcomponents::implement_runtime_class<PersonImplementation,Person_t>
{

std::string SayHello(){return "Hello World\n";}

};

CPPCOMPONENTS_DEFINE_FACTORY(PersonImplementation);

Наконец, вот основная программа (назовите ее example1.cpp), которая использует вашу реализацию

#include "library.h"#include <iostream>

int main(){
Person p;
std::cout << p.SayHello();

}

Для сборки программы вам необходимо скачать cppcomponents (просто клонируйте по ссылке git выше). Это библиотека только для заголовков и требует только компилятора c ++ 11.

Вот как бы вы это сделали на Windows

cl /EHsc example1.cpp /I pathtocppcomponents

g++ -std=c++11 library.cpp -o library.dll -shared -I pathtocppcomponents

где pathocppcomponents является каталогом cppcomponents.
Я предполагаю, что у вас есть cl и g ++ на вашем пути.

Чтобы запустить программу, убедитесь, что library.dll находится в том же каталоге, что и example1.exe, и запустите example1.exe.

Эта библиотека требует достаточно совместимой поддержки c ++ 11, поэтому требуется предварительный просмотр MSVC 2013 и, по крайней мере, g ++ 4.7. Эта библиотека работает как в Windows, так и в Linux.

2

Насколько я знаю, ответ — нет, и вы должны справиться с этим самостоятельно с небольшим количеством «взлома» и модификаций, например, вашего t переменная, которая является std::string может быть «внешним» к интерфейсу C t.c_str() так как c_str возвращает const char * это тип, который C понимает без каких-либо проблем.

Лично я не нахожу C ++ сложным, я тоже не вижу этой «проблемы ABI», я имею в виду, что нет ничего идеального, но вы выводите на C всю свою кодовую базу, чтобы «решить» эту проблему? Просто используйте C в первую очередь, также C — это нелегкий язык, например, в C нет даже понятия «строка», и проблемы, которые тривиально решить в C ++, сохраняя все в безопасности типов, действительно сложно в C, если вы хотите достичь той же цели.

Я думаю, что вы зашли слишком далеко с этим, и вы усложняете ситуацию, так как сейчас у вас есть 3 + 1 основных опций на самых популярных платформах:

  • libsupc ++
  • libcxxrt
  • Libc ++ ABI
  • плюс ABI для MSVC по вашему выбору (он же «только бог знает»)

для меня в linux libsupc ++ работает очень хорошо, я слежу за проектом abi libc ++ и не вижу большой проблемы, единственная реальная проблема в том, что llvm в настоящее время в основном ориентирован на Apple, так что нет реальной и хорошей поддержки для других платформ, но libc ++ abi компилируется и работает достаточно хорошо и на linux (хотя это в принципе бесполезно и бессмысленно, на linux уже есть libsupc ++.).

Я также никогда бы не использовал MSVC под Windows, по моему мнению, лучше придерживаться GCC-подобного компилятора, такого как mingw, у вас есть новейшие функции, и вы можете значительно упростить свою кодовую базу и фазу сборки.

1
По вопросам рекламы ammmcru@yandex.ru
Adblock
detector