首页 > 试题广场 >

调用动态连接库的函数有哪几种方法?

[问答题]
调用动态连接库的函数有哪几种方法?
推荐
调用一个DLL中的函数有两种方法: 1.载入时动态链接(load-time dynamic linking),模块非常明确调用某个导出函数,使得他们就像本地函数一样。这需要链接时链接那些函数所在DLL的导入库,导入库向系统提供了载入DLL时所需的信息及DLL函数定位。 2.运行时动态链接(run-time dynamic linking),运行时可以通过LoadLibrary或LoadLibraryEx函数载入DLL。DLL载入后,模块可以通过调用GetProcAddress获取DLL函数的出口地址,然后就可以通过返回的函数指针调用DLL函数了。如此即可避免导入库文件了。
编辑于 2015-02-04 11:39:04 回复(0)
    主要有两种方法:第一种在项目的配置工程的Link设置中链入动态链接库对应的符号文件(lib文件),并在相应的代码文件中#include其对应的头文件,这样直接调用其函数即可。第二种方法是使用Windows提供的LoadLibrary首先加载相应的dll文件,然后在使用GetProcAdress这个API获得需要调用的函数的指针,最后需要调用FreeLibrary释放这个dll文件,这种方法不需要使用lib文件。
    还有两种偏门的方法,上述两种方法只能调用Dll的导出函数,可以通过反汇编获得dll中函数的偏移地址并推测其函数原型,加载这个DLL后也可以用获得的指针进行调用,这种情况下这个DLL一般不是我们自己写的。第二种情况如果这个DLL是我们自己写的,我们可以我们可以只导出一个DLL的初始化函数和卸载函数,DLL模块和我们的调用模块遵循一个统一的数据结构,在加载DLL时通过调用这个DLL的初始化函数填充这个统一的数据结构,也可以将DLL的函数指针填充过来,我们在调用模块中就可以直接调用这个函数了。第二种方法十分适合模块化一个程序功能。
发表于 2015-07-03 10:12:00 回复(0)
<pre class="best-text mb-10">一般有两种调用方式: 1、静态调用。将编译之后的dll和所对应的<a href="https://www.baidu.com/s?wd=lib%E6%96%87%E4%BB%B6&amp;tn=44039180_cpr&amp;fenlei=mv6quAkxTZn0IZRqIHckPjm4nH00T1Y4PAm1uWIbuj99uhw-rHn40ZwV5Hcvrjm3rH6sPfKWUMw85HfYnjn4nH6sgvPsT6K1TL0qnfK1TL0z5HD0IgF_5y9YIZ0lQzqlpA-bmyt8mh7GuZR8mvqVQL7dugPYpyq8Q1nkPWm4nHDLP0" target="_blank">lib文件</a>放到要调用它们的工程所在路径,然后添加如下代码: #pragma comment(lib,"dege.lib") extern "C" __declspec(dllimport) FuncA(//参数); 然后可以直接使用FuncA函数了,跟普通函数一样。这个其实是一个<a href="https://www.baidu.com/s?wd=%E9%9D%99%E6%80%81%E5%BA%93&amp;tn=44039180_cpr&amp;fenlei=mv6quAkxTZn0IZRqIHckPjm4nH00T1Y4PAm1uWIbuj99uhw-rHn40ZwV5Hcvrjm3rH6sPfKWUMw85HfYnjn4nH6sgvPsT6K1TL0qnfK1TL0z5HD0IgF_5y9YIZ0lQzqlpA-bmyt8mh7GuZR8mvqVQL7dugPYpyq8Q1nkPWm4nHDLP0" target="_blank">静态库</a>,因为你很可能没有<a href="https://www.baidu.com/s?wd=lib%E6%96%87%E4%BB%B6&amp;tn=44039180_cpr&amp;fenlei=mv6quAkxTZn0IZRqIHckPjm4nH00T1Y4PAm1uWIbuj99uhw-rHn40ZwV5Hcvrjm3rH6sPfKWUMw85HfYnjn4nH6sgvPsT6K1TL0qnfK1TL0z5HD0IgF_5y9YIZ0lQzqlpA-bmyt8mh7GuZR8mvqVQL7dugPYpyq8Q1nkPWm4nHDLP0" target="_blank">lib文件</a>,所以建议使用第二种方式: 2、动态调用。 typedef int(*lpFunA)(int, int); //<a href="https://www.baidu.com/s?wd=%E5%AE%8F%E5%AE%9A%E4%B9%89&amp;tn=44039180_cpr&amp;fenlei=mv6quAkxTZn0IZRqIHckPjm4nH00T1Y4PAm1uWIbuj99uhw-rHn40ZwV5Hcvrjm3rH6sPfKWUMw85HfYnjn4nH6sgvPsT6K1TL0qnfK1TL0z5HD0IgF_5y9YIZ0lQzqlpA-bmyt8mh7GuZR8mvqVQL7dugPYpyq8Q1nkPWm4nHDLP0" target="_blank">宏定义</a><a href="https://www.baidu.com/s?wd=%E5%87%BD%E6%95%B0%E6%8C%87%E9%92%88&amp;tn=44039180_cpr&amp;fenlei=mv6quAkxTZn0IZRqIHckPjm4nH00T1Y4PAm1uWIbuj99uhw-rHn40ZwV5Hcvrjm3rH6sPfKWUMw85HfYnjn4nH6sgvPsT6K1TL0qnfK1TL0z5HD0IgF_5y9YIZ0lQzqlpA-bmyt8mh7GuZR8mvqVQL7dugPYpyq8Q1nkPWm4nHDLP0" target="_blank">函数指针</a>类型,这里假设你的FuncA是一个int型的函数,且带两个int型的参数,你可以假设为是一个求和的Add函数。 在要使用FunA的地方添加如下代码 HINSTANCE hDll;//定义个DLL句柄 lpFunA addFun;//自定义函数的指针 hDll=LoadLibrary("..\\Debug\\dege.dll");//动态加载dll,这里假设你的dll放在你要调用它的工程的debug下 if(hDll!=<a href="https://www.baidu.com/s?wd=NULL&amp;tn=44039180_cpr&amp;fenlei=mv6quAkxTZn0IZRqIHckPjm4nH00T1Y4PAm1uWIbuj99uhw-rHn40ZwV5Hcvrjm3rH6sPfKWUMw85HfYnjn4nH6sgvPsT6K1TL0qnfK1TL0z5HD0IgF_5y9YIZ0lQzqlpA-bmyt8mh7GuZR8mvqVQL7dugPYpyq8Q1nkPWm4nHDLP0" target="_blank">NULL</a>) { addFun=(lpFunA)GetProAddress(hDll,"FunA");//获得FunA的地址 if(FunA!=<a href="https://www.baidu.com/s?wd=NULL&amp;tn=44039180_cpr&amp;fenlei=mv6quAkxTZn0IZRqIHckPjm4nH00T1Y4PAm1uWIbuj99uhw-rHn40ZwV5Hcvrjm3rH6sPfKWUMw85HfYnjn4nH6sgvPsT6K1TL0qnfK1TL0z5HD0IgF_5y9YIZ0lQzqlpA-bmyt8mh7GuZR8mvqVQL7dugPYpyq8Q1nkPWm4nHDLP0" target="_blank">NULL</a>) { //这里正常使用addFun,跟普通函数一样 } FreeLibrary(hDll);//用完之后要释放句柄 }</pre>
发表于 2015-08-24 11:17:15 回复(0)
静态链接,一般是调用别人或自己写的动态库,此时一般会有对应的lib文件和头文件。程序中指定pragma comment(lib,"xxx")。
动态链接,在代码中手动调用loadlibrary,然后getprocaddress获取到导出函数地址,直接调用即可,此时可以不需要头文件,只要知道函数原型即可。
以上两种都需要导出函数。
非法调用,直接LoadLibrary,然后通过分析动态库中的函数地址和参数,如动态链接一样声明原型或者用asm直接调用。可以直接调用非导出函数,但是需要手动管理堆栈等问题。
发表于 2017-04-01 11:53:12 回复(0)
函数调用。
发表于 2016-08-27 20:02:49 回复(0)

 应用程序使用 DLL 可以采用两种方式:一种是隐式链接 ( 调用 ) ,另一种是显式链接。在使用 DLL 之前首先要知道 DLL 中函数的结构信息。 VS VC\bin 目录下提供了一个名为 Dumpbin.exe 的小程序,用它可以查看 DLL 文件中的函数结构。

隐式链接 采用静态加载的方式,比较简单,需要 .h .lib .dll 三件套。
新建 控制台应用程序 空项目 配置如下 :(非常关键)

项目 -> 属性 -> 配置属性 ->VC++ 目录 ->  包含目录 里添加头文件 testdll.h 所在的目录

项目 -> 属性 -> 配置属性 ->VC++ 目录 ->  库目录 里添加头文件 testdll.lib 所在的目录

项目 -> 属性 -> 配置属性 -> 链接器 -> 输入 ->  附加依赖项 里添加 “testdll.lib” (若有多个 lib 则以空格隔开)
还需要将 testdll.dll 复制到当前项目生成的可执行文件所在的目录

显式链接 是应用程序在执行过程中随时可以加载 DLL 文件,也可以随时卸载 DLL 文件,这是隐式链接所无法作到的,所以显式链接具有更好的灵活性,对于解释性语言更为合适。  


发表于 2015-09-05 21:45:38 回复(0)
<pre class="best-text mb-10">主要有两种方法: 1、静态调用。将编译之后的dll和所对应的<a target="_blank" href="https://www.baidu.com/s?wd=lib%E6%96%87%E4%BB%B6&amp;tn=44039180_cpr&amp;fenlei=mv6quAkxTZn0IZRqIHckPjm4nH00T1YYPWI9rHPbujRsrjmzmWRv0ZwV5Hcvrjm3rH6sPfKWUMw85HfYnjn4nH6sgvPsT6K1TL0qnfK1TL0z5HD0IgF_5y9YIZ0lQzqlpA-bmyt8mh7GuZR8mvqVQL7dugPYpyq8Q1nkPWm4nHDLP0">lib文件</a>放到要调用它们的工程所在路径,然后添加如下代码: #pragma comment(lib,"dege.lib") extern "C" __declspec(dllimport) FuncA(//参数); 然后可以直接使用FuncA函数了,跟普通函数一样。这个其实是一个<a target="_blank" href="https://www.baidu.com/s?wd=%E9%9D%99%E6%80%81%E5%BA%93&amp;tn=44039180_cpr&amp;fenlei=mv6quAkxTZn0IZRqIHckPjm4nH00T1YYPWI9rHPbujRsrjmzmWRv0ZwV5Hcvrjm3rH6sPfKWUMw85HfYnjn4nH6sgvPsT6K1TL0qnfK1TL0z5HD0IgF_5y9YIZ0lQzqlpA-bmyt8mh7GuZR8mvqVQL7dugPYpyq8Q1nkPWm4nHDLP0">静态库</a>,因为你很可能没有<a target="_blank" href="https://www.baidu.com/s?wd=lib%E6%96%87%E4%BB%B6&amp;tn=44039180_cpr&amp;fenlei=mv6quAkxTZn0IZRqIHckPjm4nH00T1YYPWI9rHPbujRsrjmzmWRv0ZwV5Hcvrjm3rH6sPfKWUMw85HfYnjn4nH6sgvPsT6K1TL0qnfK1TL0z5HD0IgF_5y9YIZ0lQzqlpA-bmyt8mh7GuZR8mvqVQL7dugPYpyq8Q1nkPWm4nHDLP0">lib文件</a>,所以建议使用第二种方式: 2、动态调用。 typedef int(*lpFunA)(int, int); //<a target="_blank" href="https://www.baidu.com/s?wd=%E5%AE%8F%E5%AE%9A%E4%B9%89&amp;tn=44039180_cpr&amp;fenlei=mv6quAkxTZn0IZRqIHckPjm4nH00T1YYPWI9rHPbujRsrjmzmWRv0ZwV5Hcvrjm3rH6sPfKWUMw85HfYnjn4nH6sgvPsT6K1TL0qnfK1TL0z5HD0IgF_5y9YIZ0lQzqlpA-bmyt8mh7GuZR8mvqVQL7dugPYpyq8Q1nkPWm4nHDLP0">宏定义</a><a target="_blank" href="https://www.baidu.com/s?wd=%E5%87%BD%E6%95%B0%E6%8C%87%E9%92%88&amp;tn=44039180_cpr&amp;fenlei=mv6quAkxTZn0IZRqIHckPjm4nH00T1YYPWI9rHPbujRsrjmzmWRv0ZwV5Hcvrjm3rH6sPfKWUMw85HfYnjn4nH6sgvPsT6K1TL0qnfK1TL0z5HD0IgF_5y9YIZ0lQzqlpA-bmyt8mh7GuZR8mvqVQL7dugPYpyq8Q1nkPWm4nHDLP0">函数指针</a>类型,这里假设你的FuncA是一个int型的函数,且带两个int型的参数,你可以假设为是一个求和的Add函数。 在要使用FunA的地方添加如下代码 HINSTANCE hDll;//定义个DLL句柄 lpFunA addFun;//自定义函数的指针 hDll=LoadLibrary("..\\Debug\\dege.dll");//动态加载dll,这里假设你的dll放在你要调用它的工程的debug下 if(hDll!=<a target="_blank" href="https://www.baidu.com/s?wd=null&amp;tn=44039180_cpr&amp;fenlei=mv6quAkxTZn0IZRqIHckPjm4nH00T1YYPWI9rHPbujRsrjmzmWRv0ZwV5Hcvrjm3rH6sPfKWUMw85HfYnjn4nH6sgvPsT6K1TL0qnfK1TL0z5HD0IgF_5y9YIZ0lQzqlpA-bmyt8mh7GuZR8mvqVQL7dugPYpyq8Q1nkPWm4nHDLP0">null</a>) { addFun=(lpFunA)GetProAddress(hDll,"FunA");//获得FunA的地址 if(FunA!=<a target="_blank" href="https://www.baidu.com/s?wd=null&amp;tn=44039180_cpr&amp;fenlei=mv6quAkxTZn0IZRqIHckPjm4nH00T1YYPWI9rHPbujRsrjmzmWRv0ZwV5Hcvrjm3rH6sPfKWUMw85HfYnjn4nH6sgvPsT6K1TL0qnfK1TL0z5HD0IgF_5y9YIZ0lQzqlpA-bmyt8mh7GuZR8mvqVQL7dugPYpyq8Q1nkPWm4nHDLP0">null</a>) { //这里正常使用addFun,跟普通函数一样 } FreeLibrary(hDll);//用完之后要释放句柄 }</pre> <br />
发表于 2015-08-29 14:46:05 回复(0)
<pre class="best-text mb-10">一般有两种调用方式: 1、静态调用。将编译之后的dll和所对应的<a href="https://www.baidu.com/s?wd=lib%E6%96%87%E4%BB%B6&amp;tn=44039180_cpr&amp;fenlei=mv6quAkxTZn0IZRqIHckPjm4nH00T1YLmyNBnAF-PHTvrH6zmW-B0ZwV5Hcvrjm3rH6sPfKWUMw85HfYnjn4nH6sgvPsT6K1TL0qnfK1TL0z5HD0IgF_5y9YIZ0lQzqlpA-bmyt8mh7GuZR8mvqVQL7dugPYpyq8Q1nkPWm4nHDLP0" target="_blank">lib文件</a>放到要调用它们的工程所在路径,然后添加如下代码: #pragma comment(lib,"dege.lib") extern "C" __declspec(dllimport) FuncA(//参数); 然后可以直接使用FuncA函数了,跟普通函数一样。这个其实是一个<a href="https://www.baidu.com/s?wd=%E9%9D%99%E6%80%81%E5%BA%93&amp;tn=44039180_cpr&amp;fenlei=mv6quAkxTZn0IZRqIHckPjm4nH00T1YLmyNBnAF-PHTvrH6zmW-B0ZwV5Hcvrjm3rH6sPfKWUMw85HfYnjn4nH6sgvPsT6K1TL0qnfK1TL0z5HD0IgF_5y9YIZ0lQzqlpA-bmyt8mh7GuZR8mvqVQL7dugPYpyq8Q1nkPWm4nHDLP0" target="_blank">静态库</a>,因为你很可能没有<a href="https://www.baidu.com/s?wd=lib%E6%96%87%E4%BB%B6&amp;tn=44039180_cpr&amp;fenlei=mv6quAkxTZn0IZRqIHckPjm4nH00T1YLmyNBnAF-PHTvrH6zmW-B0ZwV5Hcvrjm3rH6sPfKWUMw85HfYnjn4nH6sgvPsT6K1TL0qnfK1TL0z5HD0IgF_5y9YIZ0lQzqlpA-bmyt8mh7GuZR8mvqVQL7dugPYpyq8Q1nkPWm4nHDLP0" target="_blank">lib文件</a>,所以建议使用第二种方式: 2、动态调用。 typedef int(*lpFunA)(int, int); //<a href="https://www.baidu.com/s?wd=%E5%AE%8F%E5%AE%9A%E4%B9%89&amp;tn=44039180_cpr&amp;fenlei=mv6quAkxTZn0IZRqIHckPjm4nH00T1YLmyNBnAF-PHTvrH6zmW-B0ZwV5Hcvrjm3rH6sPfKWUMw85HfYnjn4nH6sgvPsT6K1TL0qnfK1TL0z5HD0IgF_5y9YIZ0lQzqlpA-bmyt8mh7GuZR8mvqVQL7dugPYpyq8Q1nkPWm4nHDLP0" target="_blank">宏定义</a><a href="https://www.baidu.com/s?wd=%E5%87%BD%E6%95%B0%E6%8C%87%E9%92%88&amp;tn=44039180_cpr&amp;fenlei=mv6quAkxTZn0IZRqIHckPjm4nH00T1YLmyNBnAF-PHTvrH6zmW-B0ZwV5Hcvrjm3rH6sPfKWUMw85HfYnjn4nH6sgvPsT6K1TL0qnfK1TL0z5HD0IgF_5y9YIZ0lQzqlpA-bmyt8mh7GuZR8mvqVQL7dugPYpyq8Q1nkPWm4nHDLP0" target="_blank">函数指针</a>类型,这里假设你的FuncA是一个int型的函数,且带两个int型的参数,你可以假设为是一个求和的Add函数。 在要使用FunA的地方添加如下代码 HINSTANCE hDll;//定义个DLL句柄 lpFunA addFun;//自定义函数的指针 hDll=LoadLibrary("..\\Debug\\dege.dll");//动态加载dll,这里假设你的dll放在你要调用它的工程的debug下 if(hDll!=<a href="https://www.baidu.com/s?wd=NULL&amp;tn=44039180_cpr&amp;fenlei=mv6quAkxTZn0IZRqIHckPjm4nH00T1YLmyNBnAF-PHTvrH6zmW-B0ZwV5Hcvrjm3rH6sPfKWUMw85HfYnjn4nH6sgvPsT6K1TL0qnfK1TL0z5HD0IgF_5y9YIZ0lQzqlpA-bmyt8mh7GuZR8mvqVQL7dugPYpyq8Q1nkPWm4nHDLP0" target="_blank">NULL</a>) { addFun=(lpFunA)GetProAddress(hDll,"FunA");//获得FunA的地址 if(FunA!=<a href="https://www.baidu.com/s?wd=NULL&amp;tn=44039180_cpr&amp;fenlei=mv6quAkxTZn0IZRqIHckPjm4nH00T1YLmyNBnAF-PHTvrH6zmW-B0ZwV5Hcvrjm3rH6sPfKWUMw85HfYnjn4nH6sgvPsT6K1TL0qnfK1TL0z5HD0IgF_5y9YIZ0lQzqlpA-bmyt8mh7GuZR8mvqVQL7dugPYpyq8Q1nkPWm4nHDLP0" target="_blank">NULL</a>) { //这里正常使用addFun,跟普通函数一样 } FreeLibrary(hDll);//用完之后要释放句柄 }</pre>
发表于 2015-08-29 10:18:15 回复(0)
通过export导出类对象指针或者直接导出函数
发表于 2015-05-09 22:29:47 回复(0)
1. 静态调用。将编译之后的dll和所对应的lib文件放到要调用它们的工程所在路径.
2. 动态调用

发表于 2015-04-16 21:44:14 回复(0)
隐式调用和显示调用。
隐式调用是用导入头文件的方式。当进程启动时,自动加载动态库。
显示调用是用系统提供的API的方法进行动态加载,动态释放。这些都是要程序员自己进行控制。不如隐式调用方便。
发表于 2015-04-03 11:22:27 回复(0)
静态调用
#pragma comment(lib,"MFC_DLL.lib")
extern "C" _declspec(dllimport) int _stdcall Add_new(int a,int b);
动态调用
#incldue<windows.h>
typedef int (* lpAddFun)(int ,int);

发表于 2015-04-01 18:44:26 回复(0)