2010-09-23 75 views
1

我有一个共享库lib.so包含一个类Foo。我正在动态加载(在UNIX上为dlopenlib.so。加载后,我想创建一个Foo的实例。
我可以简单地使用new运营商创建一个Foo的对象,或者我将不得不创建一个导出的工厂方法放在lib.so将为我创建该对象?是从共享库中导出类的构造函数吗?

其实问题是如果Foo的构造函数被导出,并且它可以简单地用new运算符调用。我认为UNIX上的共享库中的所有类和方法都是默认导出的,我不必像在Windows上那样显式导出它们。

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

回答

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

我相信GCC维护一个兼容的C++ API回到版本3.3.6。请参阅http://stackoverflow.com/questions/3718746/g-version-compatibility – 2010-09-23 13:42:49

+0

@Zan:这不会改变问题:具有其他编译器的用户将无法导入使用gcc编译的共享对象。 – 2010-09-23 13:47:54

+2

你说过“*相同*编译器的不同版本”,这就是我发表评论的原因。 – 2010-09-23 13:58:59

0

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

使用GCC时,它曾经是默认情况下导出所有内容的情况,您无法真正控制它。在几年前,这种情况随着被添加的属性而改变(我无法确切记得它被称为什么,但它的工作方式类似于等效的Microsoft __declspec(dllexport))。

因此,如果您定义一个类并将其标记为导出(但是您选择这样做),那么将会导出它的构造函数。然而,正如前面的招贴画所提到的,由于C++的特性,符号的名称会根据您使用的编译器而变化,并且有时也会根据C++编译器的版本而变化。这不一定是个问题,它取决于你想如何使用事物,但这确实意味着你必须意识到这一点。

+0

知名度选项和属性... – Tomek 2010-09-23 19:37:07

相关问题