dll 与 Visual Studio 之间的循环依赖

2021-12-25 00:00:00 circular-dependency dll c++

我在两个函数之间存在循环依赖.我希望这些函数中的每一个都驻留在自己的 dll 中.是否可以使用 Visual Studio 来构建它?

I have a circular dependency between two functions. I would like each of these functions to reside in its own dll. Is it possible to build this with visual studio?

foo(int i)
{
   if (i > 0)
      bar(i -i);
}

-> 应该编译成 foo.dll

-> should compile into foo.dll

bar(int i)
{
   if (i > 0)
      foo(i - i);
}

-> 应该编译成 bar.dll

-> should compile into bar.dll

我在 Visual Studio 中创建了两个项目,一个用于 foo,一个用于 bar.通过使用参考"并编译几次,我设法获得了我想要的 dll.但是,我想知道 Visual Studio 是否提供了一种以干净的方式执行此操作的方法.

I have created two projects in visual studio, one for foo and one for bar. By playing with the 'References' and compiling a few times, I managed to get the dll's that I want. I would like to know however whether visual studio offers a way to do this in a clean way.

如果foo改变了,bar不需要重新编译,因为我只依赖bar的签名,不依赖bar的实现.如果两个 dll 都存在 lib,我可以将新功能重新编译到两者中的任何一个中,并且整个系统仍然可以工作.

If foo changes, bar does not need to be recompiled, because I only depend on the signature of bar, not on the implementation of bar. If both dll's have the lib present, I can recompile new functionality into either of the two and the whole system still works.

我尝试这样做的原因是我有一个具有循环依赖关系的遗留系统,它目前是静态链接的.由于各种原因,我们想转向 dll.我们不想等到我们清理所有循环依赖.我正在考虑解决方案,并在 linux 上使用 gcc 尝试了一些东西,并且可以按照我的建议进行操作.因此,您可以拥有两个相互依赖且可以相互独立构建的共享库.

The reason I am trying this is that I have a legacy system with circular dependencies, which is currently statically linked. We want to move towards dll's for various reasons. We don't want to wait until we clean up all the circular dependencies. I was thinking about solutions and tried out some things with gcc on linux and there it is possible to do what I suggest. So you can have two shared libraries that depend on each other and can be built independent of each other.

我知道循环依赖不是一件好事,但这不是我想要的讨论.

I know that circular dependencies are not a good thing to have, but that is not the discussion I want to have.

推荐答案

它在类 Unix 系统上工作的原因是因为它们在加载时执行实际的链接解析.共享库在加载到进程之前不知道它的函数定义来自哪里.这样做的缺点是你也不知道.库可以在任何其他库(甚至首先启动进程的主二进制文件)中查找和调??用函数.默认情况下,共享库中的所有内容都会导出.

The reason it works on Unix-like systems is because they perform actual linking resolution at load time. A shared library does not know where its function definition will come from until it's loaded into a process. The downside of this is that you don't know either. A library can find and call functions in any other library (or even the main binary that launched the process in the first place). Also by default everything in a shared library is exported.

Windows 根本不能那样工作.仅导出显式导出的内容,并且所有导入都必须在库链接时解析,此时将确定将提供每个导入函数的 DLL 的身份.这需要一个导入库来链接.

Windows doesn't work like that at all. Only explicitly exported things are exported, and all imports must be resolved at library link-time, by which point the identity of the DLL that will supply each imported function has been determined. This requires an import library to link against.

但是,您可以(通过一些额外的工作)解决这个问题.使用LoadLibrary 打开任何你喜欢的DLL,然后使用GetProcAddress 来定位你想要调用的函数.这样,就没有任何限制.但是正常方法的限制是有原因的.

However, you can (with some extra work) get around this. Use LoadLibrary to open any DLL you like, and then use GetProcAddress to locate the functions you want to call. This way, there are no restrictions. But the restrictions in the normal method are there for a reason.

当您想从静态库转换为 DLL 时,听起来好像您假设您应该将每个静态库都变成一个 DLL.那不是你唯一的选择.为什么不开始将代码移动到 DLL 中,仅当您将其识别为适合分层设计且没有循环的自包含模块时呢?这样你就可以现在开始这个过程,但仍然一次攻击它.

As you want to transition from static libraries to DLLs, it sounds like you're assuming that you should make each static library into a DLL. That's not your only option. Why not start moving code into DLLs only when you identify it as a self-contained module that fits into a layered design with no circularity? That way you can begin the process now but still attack it a piece at a time.

相关文章