August 11, 2021
最近研究 emscripten 的 binding 实现,发现个自动计算函数签名的实现,挺有意思,直接看代码:
////////////////////////////////////////////////////////////////////////////////
// SignatureCode, SignatureString
////////////////////////////////////////////////////////////////////////////////
namespace internal {
template<typename T>
struct SignatureCode {};
template<>
struct SignatureCode<int> {
static constexpr char get() {
return 'i';
}
};
template<>
struct SignatureCode<void> {
static constexpr char get() {
return 'v';
}
};
template<>
struct SignatureCode<float> {
static constexpr char get() {
return 'f';
}
};
template<>
struct SignatureCode<double> {
static constexpr char get() {
return 'd';
}
};
template<typename... Args>
const char* getGenericSignature() {
static constexpr char signature[] = { SignatureCode<Args>::get()..., 0 };
return signature;
}
template<typename T> struct SignatureTranslator { using type = int; };
template<> struct SignatureTranslator<void> { using type = void; };
template<> struct SignatureTranslator<float> { using type = float; };
template<> struct SignatureTranslator<double> { using type = double; };
template<typename... Args>
EMSCRIPTEN_ALWAYS_INLINE const char* getSpecificSignature() {
return getGenericSignature<typename SignatureTranslator<Args>::type...>();
}
template<typename Return, typename... Args>
EMSCRIPTEN_ALWAYS_INLINE const char* getSignature(Return (*)(Args...)) {
return getSpecificSignature<Return, Args...>();
}
} // end namespace internal
其中主要用到了 C++ 的模板特化和可变参数模板两个特性,模板特化产生类型对应的符号(如 int 对应 ‘i’),可变参数模板用于提取任意函数的参数列表:getSignature 的入参是一个函数指针,结合模板,巧妙地获得了各参数的类型以及返回值类型
简单测试一下:
double testFunc(int a, float m) {
return (double)a + m;
}
int main() {
const char *sig = internal::getSignature(testFunc);
std::cout << sig << std::endl;
return 0;
}
输出:
/Users/hoganliu/CLionProjects/test/cmake-build-debug/test
Fif
Process finished with exit code 0