检查函数是否在编译时具有C-linkage [无法解析]

时间:2010-05-29 19:40:17

标签: c++ templates metaprogramming

有没有办法在编译时检查给定函数是否用C-linkage(即extern "C"}声明?

我正在开发一个插件系统。每个插件都可以为插件加载代码提供工厂功能。但是,这必须通过名称(以及后续使用GetProcAddressdlsym)来完成。这要求使用C-linkage声明函数,以防止名称错位。如果引用的函数是用C ++声明的,那么能够抛出编译错误会很好 - 链接(而不是在运行时找不到具有该名称的函数)。

以下是我的意思的简化示例:

extern "C" void my_func()
{
}

void my_other_func()
{
}

// Replace this struct with one that actually works
template<typename T>
struct is_c_linkage
{
    static const bool value = true;
};

template<typename T>
void assertCLinkage(T *func)
{
    static_assert(is_c_linkage<T>::value, "Supplied function does not have C-linkage");
}

int main()
{
    assertCLinkage(my_func); // Should compile
    assertCLinkage(my_other_func); // Should NOT compile
}

是否有可能实现is_c_linkage会导致第二个函数的编译错误,但不是第一个?我不确定它是否可能(尽管它可能作为编译器扩展存在,我仍然想知道)。感谢。

2 个答案:

答案 0 :(得分:2)

我同意Jonathan Leffler的说法,这可能是标准方式无法实现的。也许它可能会有所改变,具体取决于编译器甚至编译器的版本,但您必须尝试确定可能的方法并接受编译器的行为可能是无意的并且可能在以后的版本中“修复”的事实。 / p>

例如,对于Debian Squeeze上的g++版本4.4.4,您可能能够使用此方法为非stdcall的函数引发编译器错误:

void my_func() __attribute__((stdcall));
void my_func() { }

void my_other_func() { }

template <typename ret_, typename... args_>
struct stdcall_fun_t
{
    typedef ret_ (*type)(args_...) __attribute__((stdcall));
};

int main()
{
    stdcall_fun_t<void>::type pFn(&my_func),
        pFn2(&my_other_func);
}

g++ -std=c++0x无法编译此代码,因为:

  

SO2936360.cpp:17:错误:从'void()()'无效转换为'void()()'

第17行是pFn2的声明。如果我摆脱了这个声明,那么编译就会成功。

不幸的是,这种技术不适用于cdecl

答案 1 :(得分:0)

对于Unix / Linux,如何用'nm'分析生成的二进制文件并查找符号名称?我想这不是你的意思,但仍然是编译时间。