是否导出了共享库中的类的构造函数?

时间:2010-09-23 12:47:28

标签: c++ unix shared-libraries shared

我有一个包含类lib.so的共享库Foo。我正在动态加载(在UNIX上使用dlopenlib.so。加载后我想创建一个Foo的实例 我可以简单地使用new运算符来创建Foo的对象,或者我必须创建一个放置在lib.so中的导出工厂方法,它将为我创建该对象吗?

实际上问题是,Foo的构造函数是否已导出,是否可以使用new运算符调用它。我认为UNIX上共享库中的所有类和方法都是默认导出的,我不必像在Windows dll上那样显式导出它们。

除了隐藏创建(并可能初始化)Foo对象的方式之外,在创建共享库中包含的类对象时,还有其他原因可以使用工厂方法吗?

2 个答案:

答案 0 :(得分:0)

这种方法存在问题。特别是,当为库和程序使用不同版本的相同编译器时,您无法保证类成员函数具有相同的符号名称。

因此,请使用工厂方法和不透明的C指针类型:

// .cpp file
class Foo { ... };

// .h file
struct FooHandle;

#ifdef __cplusplus
extern "C"
{
    FooHandle* constructFoo(...);
    void releaseFoo(FooHandle*);
    int someFooMethod(FooHandle*, int param1, ...);
}
#endif

导出共享库时,始终使用C函数和不透明指针类型。

答案 1 :(得分:0)

基本答案是肯定的。然而,魔鬼在细节中。在Windows上,使用Microsoft C ++编译器,默认情况下不会为DLL导出所有符号,无论它们是方法,变量等。您需要显式导出函数,类和/或全局变量。我相信这也是Borlands编译器的情况(我可能是错的)。

对于GCC,过去一切都是默认情况下导出的,你无法控制它。从几年前开始,这种情况发生了变化,添加了一个属性(我无法回想起它的确切内容,但它的工作方式类似于等效的Microsoft __declspec(dllexport))。

因此,如果您定义一个类并将其标记为已导出(但您选择这样做),则会导出它的构造函数。但是,正如之前的海报所提到的,由于C ++的性质,符号的名称会根据您使用的编译器而有所变化,有时候,C ++编译器的版本也会变化。这不一定是一个问题,它取决于你想要如何使用东西,但它确实意味着你必须意识到它。