我正在使用 libffi,并且我创建了一个具有类似模板的类std::function
(即class Func<Ret (Args...)> { /* ... */};
。我想将返回类型(Ret
)和每个参数类型(Args
)转换为它们相应的 libffi 类型(请参阅此以供参考)。到目前为止我想出了这个:
// Member function of 'Func' class
Prepare(void)
{
// This vector holds all the type structures
std::vector<ffi_type*> argumentTypes{ GetFFIType<Args>()... };
ffi_type * returnType = GetFFIType<Ret>();
// Rest of the code below
// ....
}
其中 GetFFIType 函数实现如下:
template <typename T>
ffi_type * GetFFIType(void)
{
// We will check for any kind of pointer types
if(std::is_pointer<T>::value || std::is_array<T>::value ||
std::is_reference<T>::value || std::is_function<T>::value)
return &ffi_type_pointer;
if(std::is_enum<T>::value)
//return GetFFIType<std::underlying_type<T>::type>();
{
// Since the size of the enum may vary, we will identify the size
if(sizeof(T) == ffi_type_schar.size) return std::is_unsigned<T>::value ? &ffi_type_uchar : &ffi_type_schar;
if(sizeof(T) == ffi_type_sshort.size) return std::is_unsigned<T>::value ? &ffi_type_ushort : &ffi_type_sshort;
if(sizeof(T) == ffi_type_sint.size) return std::is_unsigned<T>::value ? &ffi_type_uint : &ffi_type_sint;
if(sizeof(T) == ffi_type_slong.size) return std::is_unsigned<T>::value ? &ffi_type_ulong : &ffi_type_slong;
}
assert(false && "cannot identify type");
}
// These are all of our specializations
template <> ffi_type * GetFFIType<void>(void) { return &ffi_type_void; }
template <> ffi_type * GetFFIType<byte>(void) { return &ffi_type_uchar; }
template <> ffi_type * GetFFIType<char>(void) { return &ffi_type_schar; }
template <> ffi_type * GetFFIType<ushort>(void) { return &ffi_type_ushort; }
template <> ffi_type * GetFFIType<short>(void) { return &ffi_type_sshort; }
template <> ffi_type * GetFFIType<uint>(void) { return &ffi_type_uint; }
template <> ffi_type * GetFFIType<int>(void) { return &ffi_type_sint; }
template <> ffi_type * GetFFIType<ulong>(void) { return &ffi_type_ulong; }
template <> ffi_type * GetFFIType<long>(void) { return &ffi_type_slong; }
template <> ffi_type * GetFFIType<float>(void) { return &ffi_type_float; }
template <> ffi_type * GetFFIType<double>(void) { return &ffi_type_double; }
template <> ffi_type * GetFFIType<long double>(void) { return &ffi_type_longdouble; }
这行得通,但显然还有一些改进的余地。如果类型无效(即类或结构),则不会在编译时识别(使用 代替会发生运行时错误assert
)。我将如何避免这种情况,并使此函数在编译期间确定类型是否有效(原始类型)?
我也不喜欢在enum
s 的情况下识别基础类型的方式。我更喜欢std::underlying_type<T>
改用(在代码中注释掉),但如果类型是 void 指针(type_traits:1762:38: error: ‘void*’ is not an enumeration type
) ,它会发出编译错误
我试图使用std::enable_if
但没有成功来实现这种行为......请告诉我是否应该解释一些事情,以防听起来有点模糊!
摘要:我想获取 GetFFIType 函数来确定编译期间的所有内容,并且该函数应仅支持原始类型(请参阅this以获得更广泛的参考)
编辑:对不起标题,没有比这更好的了:(