从DLL调用DLL [英] Calling a DLL from a DLL

查看:53
本文介绍了从DLL调用DLL的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个应用程序(.exe)调用我写的dll中的函数(让我们称之为DLL1.dll)。这反过来调用其他dll中的函数(其中一些我写的,其他我没有例如opencv)。一切都很好,但是当我运行.exe时,我收到消息
喜欢:


"程序入口点xxx @ xxx ...无法在动态中找到链接库DLL1.dll


问题是这些函数不在DLL1.dll中,它们在其他DLL中 由第一个DLL调用/链接的。所有dll都与.exe位于同一文件夹中。我正在使用visual studio 2010 pro 64bit。我在vs 2015上尝试了它并且问题不存在。


我通过简单地链接到相关链接来链接所有dll。 lib,包括标题。项目文件由CMake在每种情况下创建。


任何想法?



谢谢



Derek

解决方案

入口点存在于dll。  导入库(使用.dll构建的关联.lib)包含一个代理函数,在调用时,将确保加载dll并获取所需内容的proc地址并调用它。


DLL1.dll中的代码必须链接到它使用的所有其他dll的导入库。   e.g。 DLL2.lib,DLL3.lib等。


在这种情况下,xxx @ xxx真的很重要。


案例1:


当你看到xxx @ xxx时...看起来像是应该在DLL1或其他地方定义的函数吗?  如果说在DLL1.dll中找不到xxx @ xxx而xxx @ xxx是一个应该在DLL2.dll中的函数,这是一种问题
(案例1)。  您可能没有使用定义的相应dllimport或dllexport标志声明头文件。  库通常会有一个特殊的预处理器标志,你需要编译它,说明你是使用来自
原始dll(declspec(dllexport))的头文件还是来自该dll的消费者(decolpec(dllimport) ))。  声明通常采用以下形式:


dll1.h

 #ifdef IS_DLL1 
#define DLL_API __declspec(dllexport)
#else
#define DLL_API __declspec(dllimport)
#endif


void DLLAPI someFunction( );


然后DLL1的编译设置将定义IS_DLL1,而所有其他消费者则不会,从而在编译DLL1本身时定义导出,但在编译DLL1的使用者时定义导入。  此设置可以在.props文件,
或.vcxproj本身的项目属性中设置。



案例2:


但另一种问题是,如果xxx @ xxx看起来合法地应该来自DLL1.dll,但它只是找不到。  这是一个完全不同的问题。  您必须仔细检查签名。  愚蠢的东西
就像把wchar_t视为内置类型一样,只要编译器设置不同,就会导致两个看似相同的函数的签名不同。  您必须小心确切的功能是什么以及它来自何处。  如果
签名复杂且难以处理,那么尝试在某处更容易链接并尝试调用它的void foo(void)函数。  看看你是否收到相同的链接错误。


最后,确保你正在编译你认为的代码。  如果你有很多#ifdef预处理程序块,那么有时你的代码中有一个战略性的#error会让你知道你确实正在编译你认为的代码。


谨防路径。  有时您可能编译了较新版本的dll并链接到较新的implib,但是在运行时选择了较旧版本的dll,因为您尚未将其复制到输出目录中。  在调试器中使用模块
窗口来获取已加载模块的完整路径。


我可以使用一些关于签名的更具体的细节。没有找到的东西以及你希望它们被定义的dll。






I have an application (.exe) that calls functions in a dll that I wrote (let's call this DLL1.dll). This in turn calls functions in other dlls (some of which I wrote, others I didn't e.g. opencv). Everything links fine, but when I run the .exe I get messages like:

"The procedure entry point xxx@xxx... could not be located in the dynamic link library DLL1.dll

The issue is these functions are not in DLL1.dll, they are in other DLLs  that are called/linked by the first DLL. All dlls are in the same folder as the .exe. I'm using visual studio 2010 pro 64bit. I tried it on vs 2015 and the problem doesn't exist.

I'm linking all the dlls in all cases by simply linking to the associated .lib, and including the headers. The project files are created by CMake in each case.

Any ideas?

Thanks

Derek

解决方案

The entry point lives in the dll.  The import library (the associated .lib that gets built with your .dll) contains a proxy function that, when called, will ensure that the dll is loaded and will get the proc address of the required stuff and call it.

The code in your DLL1.dll will have to link against the import library for all the other dlls it uses.  e.g. DLL2.lib, DLL3.lib, etc.

It REALLY matters what xxx@xxx is, in this case.

Case 1:

When you see xxx@xxx... does that look like a function that is supposed to be defined in DLL1 or somewhere else?  If it says that xxx@xxx is not found in DLL1.dll and xxx@xxx is a function that is supposed to be in DLL2.dll that's one kind of problem (case 1).  You probably didn't declare header files with the appropriate dllimport or dllexport flags defined.  Often libraries will have a special preprocessor flag that you need to compile with that says whether you are using the header file from the original dll (declspec(dllexport)) or from a consumer of that dll (declspec(dllimport)).  The declarations are often of the form:

dll1.h

#ifdef IS_DLL1
#define DLL_API __declspec(dllexport)
#else
#define DLL_API __declspec(dllimport)
#endif


void DLLAPI someFunction();

Then the compile settings for DLL1 would define IS_DLL1, and all other consumers would not, thereby defining the export while compiling DLL1 itself, but defining an import when compiling the consumers of DLL1.  This setting may be set in a .props file, or in the project properties for the .vcxproj itself.

Case 2:

But the other kind of problem is if xxx@xxx looks like it's legitimately supposed to be from DLL1.dll but it's just not being found.  That's a completely different kind of problem.  You have to examine the signature carefully.  Silly things like treat wchar_t as built-in type can cause the signature of two seemingly identical functions to be different if just the compiler settings are different.  You have to be careful about what the exact function is and where it comes from.  If the signature is complicated and unwieldy, then try just adding a void foo(void) function somewhere that is easier to link and try calling that.  See if you get the same link error or not.

And finally, make sure you are compiling the code you think you are.  If you have lots of #ifdef preprocessor blocks then sometimes a strategically placed #error in your code will let you know that you are indeed compiling the code you think you are.

Beware of paths.  Sometimes you may have compiled a newer version of your dll and linked against a newer implib, but an older version of your dll was picked up at runtime because you haven't copied it to the output directory.  make use of the modules window in the debugger to get the full path of the modules that were loaded.

I could use a few more specific details about the signatures of the things that aren't being located and which dlls you expect them to be defined in.



这篇关于从DLL调用DLL的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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