我创建了一个共享库,并使用默认的符号可见性“隐藏”,即,我必须明确修改任何应导出的可见性。此外,我在头文件中定义了模板,并在库的源文件中显式地示例化它们,以强制编译(并对库用户隐藏实现)。对于此头文件foo.hpp
#include <gmpxx.h>
template <typename Number>
__attribute__((visibility("default")))
Number add(const Number& a, const Number& b);
字符串
这个源文件foo.cpp
#include "foo.hpp"
template <typename Number>
Number add(const Number& a, const Number& b)
{
return a + b;
}
template double add(const double& a, const double& b);
template int add(const int& a, const int& b);
template mpq_class add(const mpq_class& a, const mpq_class& b);
型
编译与
g++ -fPIC -fvisibility=hidden -c foo.cpp
g++ -fPIC -shared -o libfoo.so foo.o
型
给出以下(相关)符号(通过nm -CD libfoo.so
获得):
__gmpq_add
__gmpq_init
double add<double>(double const&, double const&)
int add<int>(int const&, int const&)
型
但是,我也希望mpq_class
实现有一个符号。当然,如果我现在链接到这个库并尝试调用add<mpq_class>
,那么我会得到一个未定义的符号错误。我可以通过在foo.cpp
中为mpq_class
添加一个显式的示例化来强制导出,该示例化被显式地标记为导出:
template <>
__attribute__((visibility("default")))
mpq_class add(const mpq_class& a, const mpq_class& b)
{
return a + b;
}
型
当然,这没有多大意义,因为我重复了代码,或者我必须为每个这样的函数提供一个联合实现。对于模板类,这似乎只会发生在构造函数和析构函数上,而不会发生在成员上。
我想知道为什么会这样。我猜这是因为mpq_class本身就是一个模板类,但我觉得很奇怪。
1条答案
按热度按时间eagi6jfj1#
这个线程可能是一个僵尸,但我正在研究这个问题,并认为这些信息可能会帮助别人!
我从这段代码开始:
在头文件中:
字符串
在C++文件中:
型
然后我从客户端MySourceFile.cpp使用调用size()。
这在Windows/Visual Studio上工作正常,但在Linux/gcc上使用-fvisibility=hidden时,它会给出如下错误:
型
解决方案是将MY_LIB_API放在每个声明中,因此在头文件中:
型
我猜是
不幸的是,使用单词“default”表示非隐藏,而不是表示使用命令行上指定的默认值,这使得这一切有点迟钝。