简体   繁体   English

如何在Windows上使用Visual C ++强制加载链接库

[英]How to force a linked library to load using Visual C++ on Windows

I am trying to handle a project with multiple dynamic libraries, in the libraries some global objects are created and registered in a list so that the executable can use them to build other things. 我正在尝试处理具有多个动态库的项目,在库中创建一些全局对象并在列表中注册,以便可执行文件可以使用它们来构建其他内容。 In the executable there's no reference to any function of any library, it just needs the objects, and then it knows what to do. 在可执行文件中,没有任何库的任何函数的引用,它只需要对象,然后它知道该怎么做。 These libraries are intended to work like plugins that are chosen at link time. 这些库旨在像链接时选择的插件一样工作。

Ideally when compiling ExecutableProject I link LibraryA , an object of type A gets created (by some code that's compiled in the library) and ExecutableProject does things because of it, using functions in LibraryA . 理想情况下,在编译ExecutableProject I链接LibraryA ,会创建A类型的对象(通过在库中编译的一些代码),并且ExecutableProject会使用LibraryA函数来完成它。 If instead I link LibraryB then an object of type B gets created and other things happen. 如果相反,我链接LibraryB然后创建类型B的对象,并发生其他事情。

The problem is, since ExecutableProject does not directly use any function or class in the library, the library is not loaded, and objects are never created. 问题是,由于ExecutableProject不直接使用库中的任何函数或类,因此不会加载库,也不会创建对象。

I have found some workarounds: 我找到了一些解决方法:

  1. I can use /INCLUDE:symbol at link time when compiling ExecutableProject , where symbol is any symbol exported in LibraryA or LibraryB . 编译ExecutableProject ,我可以在链接时使用/INCLUDE:symbol ,其中symbol是在LibraryALibraryB导出的任何符号。 I don't like this because I have to know the decorated name of a function in the library, which is not always available. 我不喜欢这个,因为我必须知道库中函数的装饰名称,这并不总是可用的。 Also, it's not elegant. 而且,它不优雅。
  2. I can use a dummy variable. 我可以使用虚拟变量。 I could put __declspec(dllexport) int force_link_A_or_B; 我可以把__declspec(dllexport) int force_link_A_or_B; in LibraryA and LibraryB and __declspec(dllimport) extern int force_link_A_or_B; LibraryALibraryB__declspec(dllimport) extern int force_link_A_or_B; in ExecutableProject . ExecutableProject I don't like this because if I had more libraries I'd have to add a variable for each of them. 我不喜欢这个,因为如果我有更多的库,我必须为每个库添加一个变量。 Basically although the code in ExecutableProject does not know which libraries will be linked, it still needs to know how many of them can be linked together. 基本上虽然ExecutableProject中的代码不知道将链接哪些库,但它仍然需要知道它们中有多少可以链接在一起。

On Linux, using gcc and ld, it's very easy to solve this problem, all it takes is a simple linker flag -Wl,--no-as-needed . 在Linux上,使用gcc和ld,很容易解决这个问题,所需要的只是一个简单的链接器标志-Wl,--no-as-needed Is there any way to do this using Visual Studio? 有没有办法使用Visual Studio? I would be happy if there was something that worked like /INCLUDE but used entire libraries instead of symbols and did not need decorated names. 如果有一些像/INCLUDE一样的东西但是使用整个库而不是符号并且不需要装饰名称,我会很高兴。

Thanks 谢谢

EDIT: I have been asked to clarify how this design is intended to work. 编辑:我被要求澄清这个设计是如何工作的。 Ideally, when I compile ExecutableProject I link LibraryA or B and an object is created. 理想情况下,当我编译ExecutableProject我链接LibraryAB并创建一个对象。

`ClassA A;`

This is placed outside all functions in a source file that is compiled in LibraryA . 它位于LibraryA编译的源文件中的所有函数之外。 Same thing happens in LibraryB . 同样的事情发生在LibraryB The key here is that ClassA and ClassB inherit from a BaseClass that ExecutableProject knows well. 这里的关键是ClassAClassB继承自ExecutableProject熟悉的BaseClass When the object is created, the BaseClass constructor is run, and inside it a BaseClass* pointer pointing to this (therefore the derived object) is saved, and ExecutableProject uses that pointer. 创建对象时,将运行BaseClass构造函数,并在其中保存指向thisBaseClass*指针(因此派生对象),并且ExecutableProject使用该指针。 It does not need to know anything about the derived classes, because it uses only a BaseClass pointer, but when it calls virtual functions from it, different functions are executed depending on the actual type of the pointed object. 它不需要知道派生类的任何内容,因为它只使用BaseClass指针,但是当它从中调用虚函数时,根据指向对象的实际类型执行不同的函数。 If there were more objects instead that just two alternatives, I would save BaseClass pointers in a list or a map, and let ExecutableProject access it. 如果有更多的对象只有两个替代品,我会在列表或地图中保存BaseClass指针,并让ExecutableProject访问它。

Don't try this. 不要试试这个。 The design is fundamentally flawed. 设计存在根本缺陷。

In particular, since you are not making any explicit calls to the DLL, you would rely only on object A being created via an implicit call to DllMain . 特别是,由于您没有对DLL进行任何显式调用,因此您将仅依赖于通过对DllMain的隐式调用创建的对象A

But under Windows rules, you are barred from doing anything interesting in or from DllMain , so object A cannot be very useful. 但是在Windows规则下,你被禁止在DllMain做任何有趣的事情,所以对象A不是很有用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM