[英]Is the constructor of a class from a shared library exported?
I have a shared library lib.so
containing a class Foo
. 我有一个包含类
Foo
的共享库lib.so
I'm dynamically loading (with dlopen
on UNIX) lib.so
. 我正在动态加载(在UNIX上为
dlopen
) lib.so
。 After loading I want to create an instance of Foo
. 加载后,我想创建一个
Foo
的实例。
Can I simply use new
operator to create an object of Foo
, or I would have to create an exported factory method placed in lib.so
that will create that object for me? 我可以简单地使用
new
运算符创建Foo
的对象,还是必须创建放置在lib.so
中的导出工厂方法,以便为我创建该对象?
Actually, the question would be if the constructor of Foo
is exported and if it could simply be called with new
operator. 实际上,问题是是否可以导出
Foo
的构造函数,以及是否可以简单地使用new
运算符调用它。 I think that all classes and methods within the shared library on UNIX are by default exported, and I don't have to export them explicitly as on Windows dll. 我认为默认情况下会导出UNIX上共享库中的所有类和方法,而不必像在Windows dll上那样显式导出它们。
Besides hiding the way of creating (and possibly initializing) object of Foo
, are there any other reasons for using the factory method when creating object of class contained in shared library? 除了隐藏创建(可能初始化)
Foo
对象的方式之外,在创建共享库中包含的类的对象时,还有其他使用工厂方法的原因吗?
The basic answer is yes. 基本答案是肯定的。 The devil is in the details however.
然而,细节在于魔鬼。 On Windows, using the Microsoft C++ compiler, ALL symbols, whether they are methods, variables, etc. are not exported by default for a DLL.
在Windows上,使用Microsoft C ++编译器,默认情况下不会为DLL导出所有符号,无论它们是方法,变量等。 You need to explicitly export functions, classes, and/or global variables.
您需要显式导出函数,类和/或全局变量。 I beleive this is also the case for Borlands compiler as well (I could be wrong).
我相信Borlands编译器也是如此(我可能是错误的)。
With GCC it used to be the case that everything was exported by default and you couldn't really control it. 使用GCC以前,所有内容默认情况下都是导出的,您无法真正控制它。 As of a couple of years ago this changed with an attribute that was added (I can't recall exactly what it was called but it worked in a way similar to the equivalent Microsoft __declspec(dllexport) ).
几年前,这种情况发生了变化,增加了一个属性(我不记得确切的名字,但是它的工作方式类似于等效的Microsoft __declspec(dllexport))。
So if you define a class and mark it as exported (however you choose to do so), it will have it's constructor exported. 因此,如果您定义一个类并将其标记为已导出(无论您选择这样做),它将被导出构造函数。 However, as the previous poster mentions, due to the nature of C++, the name of the symbol changes depending on what compiler you use, and also, sometimes, what version of the C++ compiler.
但是,正如先前的海报所提到的,由于C ++的性质,符号的名称会根据您使用的编译器以及有时的C ++编译器版本而变化。 This isn't necessarily a problem, it depends on how you want to use things, but it does mean you have to be aware of it.
这不一定是问题,它取决于您想如何使用事物,但这确实意味着您必须意识到这一点。
There are issues with this approach. 这种方法存在问题。 In particular, when using different versions of the same compiler for the library and the program, you have no guarantee that class member functions have the same symbol name.
特别是,当对库和程序使用同一编译器的不同版本时,不能保证类成员函数具有相同的符号名。
Therefore, go with the factory approach, and opaque C pointer types: 因此,请使用工厂方法和不透明的C指针类型:
// .cpp file
class Foo { ... };
// .h file
struct FooHandle;
#ifdef __cplusplus
extern "C"
{
FooHandle* constructFoo(...);
void releaseFoo(FooHandle*);
int someFooMethod(FooHandle*, int param1, ...);
}
#endif
Always use C functions and opaque pointer types when exporting shared libraries. 导出共享库时,请始终使用C函数和不透明的指针类型。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.