我的问题与这些类似,但似乎并不完全相关:
链接到可执行文件时如何强制将目标文件包含在静态库中? https://stackoverflow.com/questions/2991927/how-to-force-inclusion-of-an-object-file-in-a-static-library-when-linking-into-ex
使用 MSVC 强制导出符号 https://stackoverflow.com/questions/444356/forcing-symbol-export-with-msvc
我得到的是这样的:
struct thingy;
struct container
{
static container& instance(); // singleton
int register_thingy(thingy*);
};
struct thingy
{
virtual ~thingy() {}
virtual int id() const = 0;
};
//template trick to force registration.
template < typename Derived >
struct registered_thingy : thingy
{
registered_thingy() : my_id(my_static_id) {}
int id() const { return my_id; }
private:
int my_id;
static int my_static_id;
}
template < typename Derived >
int registered_thingy<Derived>::my_static_id =
container::instance().register_thingy(new Derived);
现在,在一个concrete_thingy.cpp
我有的文件:
struct my_concrete_thingy : registered_thingy<my_concrete_thingy>
{
my_concrete_thingy() {} // registered_thingy's constructor not called otherwise
};
当然,上面的内容完全没有用,但是这里抽象出了真实的行为。
当在作为一个整体编译的应用程序中使用时,这会非常有效。现在的问题是,到目前为止,我无法在隐藏背后的行为的同时使用这种技术collection
在图书馆里。换句话说,我有一个thingys.lib
文件包含concrete_thingy.cpp
但当链接到可执行文件时,注册不会发生。这collection
最终存在并且工作正常,但它是空的。
现在,这是一个静态库,而不是 DLL。这可能会稍微改变问题,并且上面链接中提到的技术似乎不适用。当然,其中一个是关于函数的,我不知道如何将它应用于这些 C++ 结构。
我尝试过使用#pragma comment
方法中包含以下三行(当然是单独的)concrete_thingy.cpp
,其中没有一个起作用:
#pragma comment (linker, "/export:concrete_thingy")
#pragma comment (linker, "/export:concrete_thingy::my_static_id")
#pragma comment (linker, "/export:registered_thingy<concrete_thingy>::my_static_id")
If concrete_thingy.cpp
位于可执行文件而不是库中,一切正常。
那么,这是我的问题:
1)有可能做我想做的事吗?我猜是的,但我只是不知道如何。
2)如果可能的话,我该如何让MSVC++ 2010来做呢?
3)如果可以的话,我怎样才能以便携的方式做到这一点?
简而言之,我想做的类似于创建一个抽象工厂来创建抽象的实现。它对这些实现一无所知,这些实现是使用全局初始化技巧注册的。这些都应该位于可以由应用程序链接到的静态库中,并且这些实现应该可以通过该工厂获得。除了他们自己之外,没有人了解这些实现,因此正常的链接会导致它们及其注册全局变量消失。
这不完全是我要做的,但已经足够接近了。
编辑:==================================================== ====
看起来这种行为是“设计使然”。 MS 认识到,无论是否使用,都会出现导致副作用的对象构造,它们利用了标准中的一个漏洞,允许它们不包含未使用任何内容的翻译单元:\
/OPT:NOREF 选项的设计显然是为了在这种情况下不执行任何操作。