В моем проекте есть библиотека C ++, которую я хочу разрешить пользователю использовать через JIT-язык для вызова функций из указанной библиотеки. Для простоты предположим, что в библиотеке есть такие классы, как:
class item {
public:
item();
item( int );
~item();
// ...
};
class item_iterator {
public:
virtual ~item_iterator();
virtual bool next( item *result ) = 0;
};
class singleton_iterator : public item_iterator {
public:
singleton_iterator( item const &i );
// ...
};
Я знаю, что LLVM ничего не знает о C ++ и что один из способов вызова функций C ++ - это обернуть их в C-thunks:
extern "C" {
void thunk_item_M_new( item *addr ) {
new( addr ) item;
}
void thunk_singleton_iterator_M_new( singleton_iterator *addr, item *i ) {
new( addr ) singleton_iterator( *i );
}
bool thunk_iterator_M_next( item_iterator *that, item *result ) {
return that->next( result );
}
} // extern "C"
Первая проблема заключается в том, как выделить item
из LLVM. Я знаю, как создавать StructType
s и добавлять к ним поля, но я не хочу параллельного размещения классов C ++ - это утомительно и подвержено ошибкам.
Идея, которую я получил, состояла в том, чтобы просто добавить char[sizeof(T)]
в качестве единственного поля в StructType
для типа класса C ++:
StructType *const llvm_item_type = StructType::create( llvm_ctx, "item" );
vector<Type*> llvm_struct_types;
llvm_struct_types.push_back( ArrayType::get( IntegerType::get( llvm_ctx, 8 ), sizeof( item ) ) );
llvm_item_type->setBody( llvm_struct_types, false );
PointerType *const llvm_item_ptr_type = PointerType::getUnqual( llvm_item_type );
Я думаю, что, поскольку это StructType
, выравнивание будет правильным, а sizeof(item)
даст правильный размер. Будет ли это работать? Есть ли лучший способ?
Вторая проблема заключается в том, что, в отличие от иерархии классов C ++, между StructType
с нет отношения наследования. Если я создаю Function
, который берет llvm_iterator_type
, но пытаюсь построить Function
объект, используя llvm_singleton_iterator_type
, функция LLVM verifyModule()
жалуется мне:
Тип параметра вызова не соответствует сигнатуре функции!
Тогда я подумал, что просто буду использовать void*
везде:
Type *const llvm_void_type = Type::getVoidTy( llvm_ctx );
PointerType *const llvm_void_ptr_type = PointerType::getUnqual( llvm_void_type );
но verifyModule()
все еще жалуется на меня, потому что, очевидно, в LLVM нет автоматического приведения к void*
типам. Как я могу решить эту проблему?