[英]Is the constructor of a class from a shared library exported?
我有一个包含类Foo
的共享库lib.so
我正在动态加载(在UNIX上为dlopen
) lib.so
。 加载后,我想创建一个Foo
的实例。
我可以简单地使用new
运算符创建Foo
的对象,还是必须创建放置在lib.so
中的导出工厂方法,以便为我创建该对象?
实际上,问题是是否可以导出Foo
的构造函数,以及是否可以简单地使用new
运算符调用它。 我认为默认情况下会导出UNIX上共享库中的所有类和方法,而不必像在Windows dll上那样显式导出它们。
除了隐藏创建(可能初始化) Foo
对象的方式之外,在创建共享库中包含的类的对象时,还有其他使用工厂方法的原因吗?
基本答案是肯定的。 然而,细节在于魔鬼。 在Windows上,使用Microsoft C ++编译器,默认情况下不会为DLL导出所有符号,无论它们是方法,变量等。 您需要显式导出函数,类和/或全局变量。 我相信Borlands编译器也是如此(我可能是错误的)。
使用GCC以前,所有内容默认情况下都是导出的,您无法真正控制它。 几年前,这种情况发生了变化,增加了一个属性(我不记得确切的名字,但是它的工作方式类似于等效的Microsoft __declspec(dllexport))。
因此,如果您定义一个类并将其标记为已导出(无论您选择这样做),它将被导出构造函数。 但是,正如先前的海报所提到的,由于C ++的性质,符号的名称会根据您使用的编译器以及有时的C ++编译器版本而变化。 这不一定是问题,它取决于您想如何使用事物,但这确实意味着您必须意识到这一点。
这种方法存在问题。 特别是,当对库和程序使用同一编译器的不同版本时,不能保证类成员函数具有相同的符号名。
因此,请使用工厂方法和不透明的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函数和不透明的指针类型。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.