gpt4 book ai didi

c++ - 使用共享库进行变体处理是个好主意吗?

转载 作者:塔克拉玛干 更新时间:2023-11-03 01:13:13 24 4
gpt4 key购买 nike

我已经使用 C++ 抽象类定义了一个接口(interface)。我想为我的项目的不同变体多次实例化它(变体可以是硬件变体或操作系统变体)。我的目标是为每个变体创建共享库,并为给定项目使用正确的库,而无需重新编译任何东西。

我为了检索给定变体所需的实例,我使用的是公共(public)函数。在每个变体的 cpp 文件中,我定义了一个函数来返回该变体的实例。在主代码中,我正在对该函数进行外部声明。我打算使用返回的对象调用接口(interface)的方法。

// Interface.hpp
class Interface {
public:
virtual void routine() = 0;
};

// variantA.cpp
class variantA : public Interface {
public:
void routine() {
printf( "We are in variantA\n" );
}
} variant;

Interface& getVariant() {
return variant;
}

// variantB.cpp
class variantB : public Interface {
public:
void routine() {
printf( "We are in variantB\n" );
}
} 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

最佳答案

首先不要在使用前声明,它属于接口(interface) header ,这正是 header 的用武之地。

问题

但我担心我们得到了一个 XY problem这里:

I want to instantiate it multiple times for different variants of my project (variants can be hardware variants or OS variants). My goal is to create shared libraries for each variant and use the right one for a given project without having to re-compile anything.

这是不可能的:您通常无法为硬件或操作系统变体 a 编译 libvarianta,而为硬件或操作系统变体 b 编译 libvariantb,并在一个同时链接到 a 和 b 的程序中一起使用它们。

问题在于,您通常每次都必须重新编译是有原因的:不同的硬件和不同的操作系统通常需要不同的机器代码。即使是 printf 调用也会针对不同的编译器或操作系统转换为不同的机器代码。这就是 C++ 标准和引用与运行时和实现的含义。

此外,您通常甚至无法调用该函数,因为在使用共享链接时您会遇到 ABI 的问题。 (不是 API),这也意味着即使对于相同体系结构的相同 Microsoft 编译器版本,您也必须编译一次用于调试,一次用于发布版本(unless further precaution are followed)。

大多数库甚至通过使用预处理器在不同平台上编译不同的高级代码。

解决方案

因此,您仍然必须为您的库和库的使用者编译所有需要的不同版本,这将需要复杂的逻辑才能知道要加载哪个二进制文件。换句话说:您将不得不找到一个共享库二进制文件,如果您只是将它们简单地编译在一起,您就会得到这个二进制文件。因此,简单地静态链接它并使用一个 API 会更容易,不需要抽象类或接口(interface),至少在运行时是明智的。您可能需要在编译时做不同的事情,因为您可能没有可移植的方式来做事情。然后您可以使用预处理器宏或 compile time polymorphism .这符合 John3136 给您的建议。

回答

所以,共享链接不会解决问题,即据我了解您的问题,实现您尝试做的事情。它只会产生更复杂的问题。共享链接不是可移植的,甚至不是纯标准 C++ 的东西。然而,不同的操作系统如何尝试实现 ABI 稳定性(如 Windows 上的 COM 对象)有一些技巧,但如果您的代码需要针对不同的硬件或运行时,这仍然无法解决问题。

关于c++ - 使用共享库进行变体处理是个好主意吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58386610/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com