C ++将共享库中的导出定义用作内联

时间:2019-04-09 12:17:11

标签: c++

我想知道是否有一种简单的方法可以在共享库中内联使用定义,但是仍然可以导出符号以供其他应用程序导入。

2 个答案:

答案 0 :(得分:1)

您可以使用包装器进行导出:

// public header
MY_DLL_INTERFACE void foo(void);

// private header
inline void foo_impl(void) { … }

// impl
void foo(void) { foo_impl(); }

答案 1 :(得分:1)

根据标准文字,这是不可能的。

  

[dcl.inline]
  6.内联函数或变量应在使用过的每个翻译单元中定义,并且在每种情况下,如果具有外部链接的函数或变量在一个翻译中被声明为内联,则应具有完全相同的定义。   单位,应在出现它的所有翻译单位中以内联方式声明;无需诊断。

因此,同一函数不能在程序的一部分内联,而不能在另一部分内联。您必须使用包装器。

gcc可以导出inline函数。尝试-fkeep-inline-functions__attribute__((used))。尚不清楚这在C ++上下文中有多有用,因为根据规则,您必须导出内联函数定义以供所有人查看,然后共享库的客户端会内联它们。 Clang仅支持__attribute__((used))

如果您愿意输掉标准游戏,可以尝试忽略两个引用句子中的任何一个,并希望获得最好的成绩。我已经用gcc尝试了这两种方法,它们都似乎可以工作,但是它们都导致不确定的行为,因此无法保证。

  1. 内联函数或变量必须在每个使用了它的翻译单元中定义---忽略它。只是在不编译库时不要定义它。用__attribute__((used))标记它,以便发出符号。

    class X {
       inline void foo();
    };
    
    #ifdef BUILDING_SHARED_LIB
       void __attribute__((used)) X::foo() {}
    #endif
    
  2. 应在所有出现的翻译单元中内联声明---忽略它。在不编译库时,不要声明inline(当然也不要定义它)。用__attribute__((used))标记它,以便发出符号。

    class X {
       void foo();
    };
    
    #ifdef BUILDING_SHARED_LIB
       inline void __attribute__((used)) X::foo() {}
    #endif
    

这两种方法似乎对我都有效,但是正如我所说,不能保证,因为根据标准,这是UB。但是,Itanium ABI不在乎是否将函数声明为内联函数,因此在情况2中,可以将ABI视为提供担保。对此我不能保证。