共享库中的类的构造函数是否导出?
我有一个包含类 Foo
的共享库 lib.so
。我正在动态加载(在 UNIX 上使用 dlopen
)lib.so
。加载后我想创建一个 Foo
的实例。
我可以简单地使用 new
运算符来创建 Foo
的对象吗?或者我必须创建一个导出的工厂方法,放置在 lib.so
中会为我创建那个对象吗?
实际上,问题是 Foo
的构造函数是否已导出,以及是否可以简单地使用 new
运算符调用。我认为 UNIX 上共享库中的所有类和方法都是默认导出的,并且我不必像在 Windows dll 上那样显式导出它们。
除了隐藏Foo
创建(并可能初始化)对象的方式之外,在创建共享库中包含的类的对象时使用工厂方法还有其他原因吗?
I have a shared library lib.so
containing a class Foo
. I'm dynamically loading (with dlopen
on UNIX) lib.so
. After loading I want to create an instance of 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?
Actually, the question would be if the constructor of Foo
is exported and if it could simply be called with new
operator. 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.
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?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
基本答案是肯定的。然而,问题在于细节。在 Windows 上,使用 Microsoft C++ 编译器,默认情况下不会为 DLL 导出所有符号,无论它们是方法、变量等。您需要显式导出函数、类和/或全局变量。我相信 Borlands 编译器也是如此(我可能是错的)。
对于 GCC,过去的情况是默认导出所有内容,并且您无法真正控制它。几年前,这种情况随着添加的属性而改变(我记不清它的确切名称,但它的工作方式类似于等效的 Microsoft __declspec(dllexport) )。
因此,如果您定义一个类并将其标记为导出(无论您选择这样做),它将导出其构造函数。然而,正如上一张海报所提到的,由于 C++ 的性质,符号名称会根据您使用的编译器以及有时 C++ 编译器的版本而变化。这不一定是问题,这取决于您想要如何使用东西,但这确实意味着您必须意识到这一点。
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. 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).
With GCC it used to be the case that everything was exported by default and you couldn't really control it. 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) ).
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. 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.
这种方法存在一些问题。特别是,当库和程序使用不同版本的相同编译器时,您无法保证类成员函数具有相同的符号名称。
因此,请采用工厂方法和不透明 C 指针类型:
导出共享库时始终使用 C 函数和不透明指针类型。
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:
Always use C functions and opaque pointer types when exporting shared libraries.