标题很难取对,所以让我解释一下我的情况:
另一个团队开发了一个库。他们发布了一个头文件和一个 *.so
文件。头文件可供我们使用,我们可以将其包含在我们自己的代码中,并根据需要使用它。然而,*.so
是随我们运行的平台一起提供的。我们在构建软件时无权访问此 *.so
。因此,我们也不能真正使用头文件,因为链接器会期望 *.so
在某个时候可用。
现在我所做的是创建一个包装类,它在运行时加载 *.so
文件,然后使用 dlsym()
按名称查找函数,然后我将它们映射到函数指针。
这是唯一的选择吗?有没有一种方法可以使用头文件但告诉链接器不要在构建时解析符号,而是在我们有机会加载 *.so
文件后尝试在运行时解析它们?
请注意,这里的真实平台是 Android(通过 NDK),但希望一般的 linux 建议在这种情况下也能正常工作,因为我们有可用的 POSIX API。
最佳答案
您有几个选项,按优先顺序排列:
- 从维护者那里获取库。只提供 header 而不提供库(至少像我们在 NDK 中为库所做的 stub 库)是行不通的。
- 构建您自己的 stub 库。如果您有要公开的符号列表,这将非常简单。把
int foo; void bar() {}
在 C 文件中,用于您需要公开的所有变量和函数,并将其构建为共享库。如果您在版本脚本中有符号列表,则可以使用 Android 的 gen_stub_libs.py。为你做。 - 在头文件中用
__attribute__((weak))
标记所有符号。链接器不会提示它们丢失了。如果它们在运行时丢失,库仍将加载,但每个函数的地址将为nullptr
。在大多数情况下并不是您真正想要的,因为如果您对库的定义是错误的,您会将构建时失败转化为运行时失败,但在某些情况下这可能很方便,因为使用if (foo) 检查功能可用性更容易) { foo(); }
然后用dlsym
做类似的事情。 - 将
-Wl,--allow-shlib-undefined
添加到您的 ldflags。这比 3 更糟糕,因为它会影响您链接的所有库,但不需要您干预 header 。
关于android - 如何使用头文件正确设置动态库加载?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47084599/