如何强制在库中包含“未使用”的对象定义

2024-03-12

我的问题与这些类似,但似乎并不完全相关:

链接到可执行文件时如何强制将目标文件包含在静态库中? 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 选项的设计显然是为了在这种情况下不执行任何操作。


好吧,其他答案都是很好的尝试,但最终没有结果。我打算使用改装技巧,但其余的似乎都是转移注意力;这是有道理的,因为所讨论的模板实际上并未在其他任何地方使用,因此它没有显式实例化的事实不应该产生影响......全局的声明仍然发生在翻译单元中,它有副作用...我认为该标准不允许对其进行优化。

不幸的是,该标准没有说明是否需要包含翻译单元,这是最终的问题。我认为 C++0x 正在对此做一些事情,但也许没有......无论如何,MS 可以随意不包含该单元,并且因为它不包含全局,所以最终不包含在可执行文件中,因此其他的事情都没有发生。

我决定做的是创建一个文件“标签”变量,当然还有很多其他方法。然后将该标签分配给可全局访问的函数(它必须分配或分配自或引用被优化掉)。然后必须从可执行文件中调用该函数。

我决定这样做,因为这样其余的工作仍然像往常一样。如果我只是编写一个手动注册类型的注册函数,我最终不会改变行为。另外,我可以用这种方式做其他事情...我只需要确保任何可能属于这种性交分类的东西都有一个标签,并且该标签可以被访问。

我将编写一堆辅助宏来使这一切变得轻松。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何强制在库中包含“未使用”的对象定义 的相关文章

  • 具有子列表属性映射问题的自动映射器

    我有以下型号 Models public class Dish Required public Int64 ID get set Required public string Name get set Required public str
  • 查找哪些页面不再与写入时复制共享

    假设我在 Linux 中有一个进程 我从中fork 另一个相同的过程 后forking 因为原始进程将开始写入内存 Linux写时复制机制将为进程提供与分叉进程使用的不同的唯一物理内存页 在执行的某个时刻 我如何知道原始进程的哪些页面已被写
  • 进程何时获得 SIGABRT(信号 6)?

    C 中进程获得 SIGABRT 的场景有哪些 该信号是否始终来自进程内部 或者该信号可以从一个进程发送到另一个进程吗 有没有办法识别哪个进程正在发送该信号 abort 向调用进程发送SIGABRT信号 就是这样abort 基本上有效 abo
  • OpenCv读/写视频色差

    我试图简单地使用 openCV 打开视频 处理帧并将处理后的帧写入新的视频文件 我的问题是 即使我根本不处理帧 只是打开视频 使用 VideoCapture 读取帧并使用 VideoWriter 将它们写入新文件 输出文件看起来比输入更 绿
  • asp.net 文本框文本模式数字,仅允许数字

    我只是想知道 ASP NET 中是否有一种方法只允许文本框中的数字textmode number 当我使用这个时
  • 迭代变量并查找特定类型实例的技术

    我想迭代进程中内存中的变量 通过插件动态加载 并查找特定类型的实例 以前我可以找到特定类型 或内存中的所有类型 我可以创建类型的实例 我可以获取作为不同类型的字段包含的实例 但我无论如何都不知道只是 搜索 特定类型的实例 一种方法是使用 W
  • 为什么大多数 C 开发人员使用 Define 而不是 const? [复制]

    这个问题在这里已经有答案了 在许多程序中 define与常量具有相同的用途 例如 define FIELD WIDTH 10 const int fieldWidth 10 我通常认为第一种形式优于另一种形式 它依赖于预处理器来处理基本上是
  • 为什么要序列化对象需要 Serialized 属性

    根据我的理解 SerializedAttribute 不提供编译时检查 因为它都是在运行时完成的 如果是这样 那么为什么需要将类标记为可序列化呢 难道序列化器不能尝试序列化一个对象然后失败吗 这不就是它现在所做的吗 当某些东西被标记时 它会
  • C# 中的接口继承

    我试图解决我在编写应用程序时遇到的相当大的 对我来说 问题 请看这个 为了简单起见 我将尝试缩短代码 我有一个名为的根接口IRepository
  • C++ 异步线程同时运行

    我是 C 11 中线程的新手 我有两个线程 我想让它们同时启动 我可以想到两种方法 如下 然而 似乎它们都没有按照我的预期工作 他们在启动另一个线程之前启动一个线程 任何提示将不胜感激 另一个问题是我正在研究线程队列 所以我会有两个消费者和
  • 如何配置 WebService 返回 ArrayList 而不是 Array?

    我有一个在 jax ws 上实现的 java Web 服务 此 Web 服务返回用户的通用列表 它运行得很好 Stateless name AdminToolSessionEJB RemoteBinding jndiBinding Admi
  • 检查算术运算中的溢出情况[重复]

    这个问题在这里已经有答案了 可能的重复 检测 C C 中整数溢出的最佳方法 https stackoverflow com questions 199333 best way to detect integer overflow in c
  • 当前的 c++ 工作草案与当前标准有何不同

    通过搜索该标准的 PDF 版本 我最终找到了这个链接C 标准措辞草案 http www open std org jtc1 sc22 wg21 docs papers 2012 n3376 pdf从 2011 年开始 我意识到我可以购买最终
  • 如何将“外部模板”与由同一类中的模板化成员使用的嵌套类一起使用?

    首先 一些背景信息 我尝试以 Herb Sutter 在他的解决方案中介绍的方式使用 Pimpl 习语 得到了 101 http herbsutter com gotw 101 这在头文件中看起来像这样 include pimpl h h
  • 在 2D 中将一个点旋转另一个点

    我想知道当一个点相对于另一个点旋转一定角度时如何计算出新的坐标 我有一个块箭头 想要将其相对于箭头底部中间的点旋转角度 theta 这是允许我在两个屏幕控件之间绘制多边形所必需的 我无法使用和旋转图像 从我到目前为止所考虑的情况来看 使问题
  • 无法将类型“System.IO.Stream”隐式转换为“Java.IO.InputStream”

    我提到了一些类似的问题 但没有一个涉及IO 当我使用时 我在java中使用了相同的代码Eclipse 那次就成功了 但现在我尝试在中使用这段代码Mono for Android C 它不起作用 我正在尝试运行此代码来创建一个InputStr
  • 当我“绘制”线条时,如何将点平均分配到 LineRenderer 的宽度曲线?

    我正在使用线条渲染器创建一个 绘图 应用程序 现在我尝试使用线条渲染器上的宽度曲线启用笔压 问题在于 AnimationCurve 的 时间 值 水平轴 从 0 标准化为 1 因此我不能在每次添加位置时都在其末尾添加一个值 除非有一个我不知
  • 如何挤出平面 2D 网格并赋予其深度

    我有一组共面 连接的三角形 即二维网格 现在我需要将其在 z 轴上挤出几个单位 网格由一组顶点定义 渲染器通过与三角形数组匹配来理解这些顶点 网格示例 顶点 0 0 0 10 0 0 10 10 0 0 10 0 所以这里我们有一个二维正方
  • 如何一步步遍历目录树?

    我发现了很多关于遍历目录树的示例 但我需要一些不同的东西 我需要一个带有某种方法的类 每次调用都会从目录返回一个文件 并逐渐遍历目录树 请问我该怎么做 我正在使用函数 FindFirstFile FindNextFile 和 FindClo
  • 剪贴板在 .NET 3.5 和 4 中的行为有所不同,但为什么呢?

    我们最近将一个非常大的项目从 NET Framework 3 5 升级到 4 最初一切似乎都工作正常 但现在复制粘贴操作开始出现错误 我已经成功制作了一个小型的可复制应用程序 它显示了 NET 3 5 和 4 中的不同行为 我还找到了一种解

随机推荐