使用共享库进行变体处理是个好主意吗?
Is it a good idea to do variant handling using shared library?
我用抽象类定义了一个接口C++。我想为项目的不同变体多次实例化它(变体可以是硬件变体或操作系统变体(。我的目标是为每个变体创建共享库,并为给定项目使用正确的库,而无需重新编译任何内容。
我为了检索给定变体所需的实例,我正在使用公共函数。在每个变体的 cpp 文件中,我定义了一个函数来返回该变体的实例。在主代码中,我正在对这个函数进行外部声明。我打算使用返回的对象调用接口的方法。
// Interface.hpp
class Interface {
public:
virtual void routine() = 0;
};
// variantA.cpp
class variantA : public Interface {
public:
void routine() {
printf( "We are in variantAn" );
}
} variant;
Interface& getVariant() {
return variant;
}
// variantB.cpp
class variantB : public Interface {
public:
void routine() {
printf( "We are in variantBn" );
}
} variant;
Interface& getVariant() {
return variant;
}
// main.cpp
#include "Interface.hpp"
extern Interface& getVariant();
int main() {
Interface& interface = getVariant();
interface.routine();
}
// build.sh
g++ -c -fPIC -O0 variantA.cpp
g++ -c -fPIC -O0 variantB.cpp
g++ variantA.o -shared -o libvariantA.so
g++ variantB.o -shared -o libvariantB.so
ln -s libvariantA.so libvariant.so
g++ -L. -lvariant main.cpp -o main
主要问题:我的方法在理论上正确吗?这样做是个好主意吗?或者,这种方法有什么明显的缺陷吗?如果是这样,任何人都可以推荐我更好的方法吗?
第二个问题:我可能可以通过一些试验自己弄清楚。但我仍然发布这个,因为这可能会使该方法无法使用。问题是编译错误:
In function `main':
main.cpp:(.text+0x9): undefined reference to `getVariant()'
collect2: error: ld returned 1 exit status
首先,不要在使用前使用声明这样做,它属于接口标头,这就是标头的用途。
问题
但我担心我们在这里遇到了一个 XY 问题:
我想为我的不同变体多次实例化它 项目(变体可以是硬件变体或操作系统变体(。我的目标是 为每个变体创建共享库,并将正确的库用于 一个给定的项目,无需重新编译任何内容。
这是不可能的:看到你通常不能为硬件或操作系统变体a编译libvarianta,而为硬件或操作系统变体b编译libvariantb,并在一个同时链接到a和b的程序中一起使用它们。
问题是你通常每次都必须重新编译是有原因的:不同的硬件和不同的操作系统通常需要不同的机器代码。甚至您所做的printf
调用也会转换为不同编译器或操作系统的不同机器代码。这就是C++标准和参考对运行时和实现的意义。
此外,您通常甚至无法调用该函数,因为在使用共享链接时,您会遇到 ABI(不是 API(的问题,这也意味着即使对于相同架构的相同Microsoft编译器版本,您也必须编译一次用于调试,一次用于发布版本(除非遵循进一步的预防措施(。
大多数库甚至使用预处理器在不同的平台上编译不同的高级代码。
溶液
因此,您仍然必须为库和库的使用者编译所有需要的不同版本,这将需要一个复杂的逻辑才能知道要加载哪个二进制文件。换句话说:你必须找到一个共享库二进制文件,如果你只是简单地将它们编译在一起,你就会得到这个二进制文件。因此,简单地静态链接它并使用一个 API 会更容易,不需要抽象类或接口,至少在运行时明智。您可能需要在编译时执行不同的操作,因为您可能没有可移植的方式来执行操作。然后,可以使用预处理器宏或编译时多态性。这符合 John3136 给您的建议。
答
所以不,共享链接不会解决问题,即据我理解你的问题,实现你尝试做的事情。它只会产生更复杂的问题。共享链接不是可移植的,甚至不是纯标准C++的东西。但是,有一些技巧可以尝试不同的操作系统如何实现 ABI 稳定性(如 Windows 上的 COM 对象(,但如果代码需要针对不同的硬件或运行时,这仍然无法解决问题。
不。这似乎是一个坏主意,而不是其他人C++共享库的方式。如果它们是不同的硬件或操作系统变体,则库可能必须采用不同的格式。一个为每个变体编译相同 API 的库是正常方法。
- 什么时候在C++中返回常量引用是个好主意
- 使用嵌套函数数组是个好主意吗?
- 将std::regex设置为静态的好主意吗
- 使用共享库进行变体处理是个好主意吗?
- 使用列表<Byte>不是好主意吗?
- 用C++编写多级内联函数是个好主意吗?
- 重载参数 C++ 是个好主意吗?
- 扩展 std::vector 是个好主意吗?
- 将 int32_t 键入为 int 是个好主意吗?
- 常量参考延长对象的寿命,然后是const_cast,这是一个好主意吗?
- 使用 QT 开发服务器应用程序是个好主意吗?(QT5)
- 用 constexpr 中的工会取代reinterpret_cast - 好主意?
- 将C 11设置功能更改为带有转发的现代模板功能是一个好主意
- 在哪里使用"std::valarray"是个好主意?
- std :: tr1 :: shared_ptr throw bad_alloc,也是一个好主意
- 在构造函数中循环C++是一个好主意吗?
- 重载指向集合的指针的开始/结束是否是个好主意
- 是一个哨兵 QWidget 一个好主意(以防止在创建和填充布局时出现内存泄漏)
- 搞砸常量是个好主意吗?
- 为大型本地数据处理扩展堆栈的大小是个好主意吗