链接一个自我注册的抽象工厂 [英] linking a self-registering, abstract factory

查看:159
本文介绍了链接一个自我注册的抽象工厂的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在使用并测试一个基于这里描述的自注册抽象工厂:

I've been working with and testing a self-registering, abstract factory based upon the one described here:

http://stackoverflow.com/a/582456

在所有的测试用例中,并提供我想要的功能和重用。

In all my test cases, it works like a charm, and provides the features and reuse I wanted.

在我的项目中使用cmake链接在这个工厂已经很棘手(虽然它似乎是一个ar问题)。

Linking in this factory in my project using cmake has been quite tricky (though it seems to be more of an ar problem).

我有相同的base.hpp,derivedb.hpp / cpp和一个等价的deriveda.hpp / cpp链接的例子。在main中,我只是实例化工厂,并调用createInstance()两次,每次使用DerivedA和DerivedB。

I have the identical base.hpp, derivedb.hpp/cpp, and an equivalent deriveda.hpp/cpp to the example linked. In main, I simply instantiate the factory and call createInstance() twice, once each with "DerivedA" and "DerivedB".

p>

The executable created by the line:

g++ -o testFactory main.cpp derivedb.o deriveda.o

按预期工作。将我的派生类移动到一个库(使用cmake,但我已经测试这个与单独的ar),然后链接失败:

works as expected. Moving my derived classes into a library (using cmake, but I have tested this with ar alone as well) and then linking fails:

ar cr libbase.a deriveda.o derivedb.o
g++ -o testFactory libbase.a main.cpp

只调用第一个静态实例化(从derivedA.cpp),而不是第二个静态实例化,即

only calls the first static instantiation (from derivedA.cpp) and never the second static instantiation, i.e.

// deriveda.cpp (if listed first in the "ar" line, this gets called)
DerivedRegister<DerivedA> DerivedA::reg("DerivedA");

// derivedb.cpp (if listed second in the "ar" line, this does not get called)
DerivedRegister<DerivedB> DerivedB::reg("DerivedB");

注意,在ar行中交换两个函数仅调用derivedb.cpp静态实例化, derived.cpp实例化。

Note that swapping the two in the ar line calls only the derivedb.cpp static instantiation, and not the deriveda.cpp instantiation.

我缺少一些与ar或静态库的东西,不知何故不玩好的静态变量在C + +?

Am I missing something with ar or static libraries that somehow do not play nice with static variables in C++?

推荐答案

与直觉相反,包括链接命令中的归档与包含所有对象文件不同存档。只包括归档中解析未定义符号所需的那些目标文件。这是一件好事,如果你认为一旦没有动态链接,否则整个任何库(认为C库)将被复制到每个可执行文件。这里是ld(1)联机帮助页(linux上的GNU ld)必须说的:

Contrary to intuition, including an archive in a link command is not the same as including all of the objects files that are in the archive. Only those object files within the archive necessary to resolve undefined symbols are included. This is a good thing if you consider that once there was no dynamic linking and otherwise the entirety of any libraries (think the C library) would be duplicated into each executable. Here's what the ld(1) manpage (GNU ld on linux) has to say:


链接器只会搜索一次档案,在命令行上指定的位置。如果归档定义了在命令行上归档之前出现的某个对象中未定义的符号,则链接器将包括归档中的相应文件。但是,稍后在命令行中出现的对象中的未定义符号不会导致链接器再次搜索归档。

The linker will search an archive only once, at the location where it is specified on the command line. If the archive defines a symbol which was undefined in some object which appeared before the archive on the command line, the linker will include the appropriate file(s) from the archive. However, an undefined symbol in an object appearing later on the command line will not cause the linker to search the archive again.

没有标准的方式来包括链接的可执行文件中的档案的每个成员。在Linux上你可以使用 g ++ -Wl,-whole-archive ,在Mac OS X上你可以使用 g ++ -all_load

Unfortunately there's no standard way to include every member of an archive in the linked executable. On linux you can use g++ -Wl,-whole-archive and on Mac OS X you can use g++ -all_load.

所以使用GNU binutils ld,链接命令应该是

So with GNU binutils ld, the link command should be

g++ -o testFactory -Wl,-whole-archive libbase.a -Wl,-no-whole-archive main.cpp


b $ b

-Wl,-no-whole-archive 确保在g ++生成的最终链接命令中后面出现的任何归档将以正常方式链接。

the -Wl,-no-whole-archive ensures that any archive appearing later in the final link command generated by g++ will be linked in the normal way.

这篇关于链接一个自我注册的抽象工厂的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆