VC++调用dll的方法

来源:互联网 发布:剑灵秦义绝捏脸数据 编辑:程序博客网 时间:2024/05/04 03:15

调用DLL有两种方法:静态调用和动态调用.

(一).静态调用其步骤如下:

1.把你的youApp.DLL拷到你目标工程(需调用youApp.DLL的工程)的Debug目录下;

2.把你的youApp.lib拷到你目标工程(需调用youApp.DLL的工程)目录下;

3.把你的youApp.h(包含输出函数的定义)拷到你目标工程(需调用youApp.DLL的工程)目

录下;

4.打开你的目标工程选中工程,选择Visual C++的Project主菜单的Settings菜单;

5.执行第4步后,VC将会弹出一个对话框,在对话框的多页显示控件中选择Link页。然

后在Object/library modules输入框中输入:youApp.lib

6.选择你的目标工程Head Files加入:youApp.h文件;

7.最后在你目标工程(*.cpp,需要调用DLL中的函数)中包含你的:#include "youApp.h"

注:youApp是你DLL的工程名。

2.动态调用其程序如下:

动态调用时只需做静态调用步骤1.

{

HINSTANCE hDllInst = LoadLibrary("youApp.DLL");

if(hDllInst)

{

typedef DWORD (WINAPI *MYFUNC)(DWORD,DWORD);

MYFUNC youFuntionNameAlias = NULL; // youFuntionNameAlias 函数别名

youFuntionNameAlias = (MYFUNC)GetProcAddress

(hDllInst,"youFuntionName");

// youFuntionName 在DLL中声明的函数名

if(youFuntionNameAlias)

{

youFuntionNameAlias(param1,param2);

}

FreeLibrary(hDllInst);

}

}

显式(静态)调用:

LIB + DLL + .H,注意.H中dllexport改为dllimport

隐式(动态)调用:

DLL + 函数原型声明,先LoadLibrary,再GetProcAddress(即找到DLL中函数的地址),不用后FreeLibrary



另外在调试一个lib库是出现下面的运行错误:

Run-Time   Check   Failure   #0   -   The   value   of   ESP   was   not   properly   saved   across   a   function   call.     This   is   usually   a   result   of   calling   a   function   declared   with   one   calling   convention   with   a   function   pointer   declared   with   a   different   calling   convention.

typedef DWORD (WINAPI *MYFUNC)(DWORD,DWORD);

改为

typedef DWORD (cdecl *MYFUNC)(DWORD,DWORD);

__cdecl

目录

几种函数调用方式
几种调用约定的区别
名字修饰约定
设置方法

编辑本段几种函数调用方式

  __cdecl 是C DECLaration的缩写(declaration,声明),表示C语言默认的函数调用方法:所有参数从右到左依次入栈,这些参数由调用者清除,称为手动清栈。被调用函数不会要求调用者传递多少参数,调用者传递过多或者过少的参数,甚至完全不同的参数都不会产生编译阶段的错误。  _stdcall 是StandardCall的缩写,是C++的标准调用方式:所有参数从右到左依次入栈,如果是调用类成员的话,最后一个入栈的是this指针。这些堆栈中的参数由被调用的函数在返回后清除,使用的指令是 retnX,X表示参数占用的字节数,CPU在ret之后自动弹出X个字节的堆栈空间。称为自动清栈。函数在编译的时候就必须确定参数个数,并且调用者必须严格的控制参数的生成,不能多,不能少,否则返回后会出错。  PASCAL 是Pascal语言的函数调用方式,也可以在C/C++中使用,参数压栈顺序与前两者相反。返回时的清栈方式与_stdcall相同。  _fastcall是编译器指定的快速调用方式。由于大多数的函数参数个数很少,使用堆栈传递比较费时。因此_fastcall通常规定将前两个(或若干个)参数由寄存器传递,其余参数还是通过堆栈传递。不同编译器编译的程序规定的寄存器不同。返回方式和_stdcall相当。  _thiscall 是为了解决类成员调用中this指针传递而规定的。_thiscall要求把this指针放在特定寄存器中,该寄存器由编译器决定。VC使用ecx,Borland的C++编译器使用eax。返回方式和_stdcall相当。  _fastcall 和 _thiscall涉及的寄存器由编译器决定,因此不能用作跨编译器的接口。所以Windows上的COM对象接口都定义为_stdcall调用方式。  C中不加说明默认函数为_cdecl方式(C中也只能用这种方式),C++也一样,但是默认的调用方式可以在IDE环境中设置。  带有可变参数的函数必须且只能使用_cdecl方式,例如下面的函数:  int printf(char * fmtStr, ...);  int scanf(char * fmtStr, ...);  */几种调用约定的区别

编辑本段几种调用约定的区别

  __cdecl __fastcall与 __stdcall,三者都是调用约定(Calling convention),它决定以下内容:1)函数参数的压栈顺序,2)由调用者还是被调用者把参数弹出栈,3)以及产生函数修饰名的方法。   1、__stdcall调用约定:函数的参数自右向左通过栈传递,被调用的函数在返回前清理传送参数的内存栈,   2、_cdecl是C和C++程序的缺省调用方式。每一个调用它的函数都包含清空堆栈的代码,所以产生的可执行文件大小会比调用_stdcall函数的大。函数采用从右到左的压栈方式。注意:对于可变参数的成员函数,始终使用__cdecl的转换方式。   3、__fastcall调用约定:它是通过寄存器来传送参数的(实际上,它用ECX和EDX传送前两个双字(DWORD)或更小的参数,剩下的参数仍旧自右向左压栈传送,被调用的函数在返回前清理传送参数的内存栈)。   4、thiscall仅仅应用于"C++"成员函数。this指针存放于CX寄存器,参数从右到左压。thiscall不是关键词,因此不能被程序员指定。   5、nakedcall采用1-4的调用约定时,如果必要的话,进入函数时编译器会产生代码来保存ESI,EDI,EBX,EBP寄存器,退出函数时则产生代码恢复这些寄存器的内容。naked call不产生这样的代码。naked call不是类型修饰符,故必须和_declspec共同使用。

编辑本段名字修饰约定

  1、修饰名(Decoration name):"C"或者"C++"函数在内部(编译和链接)通过修饰名识别   2、C编译时函数名修饰约定规则:   __stdcall调用约定在输出函数名前加上一个下划线前缀,后面加上一个"@"符号和其参数的字节数,格式为_functionname@number,例如 :function(int a, int b),其修饰名为:_function@8   __cdecl调用约定仅在输出函数名前加上一个下划线前缀,格式为_functionname。   __fastcall调用约定在输出函数名前加上一个"@"符号,后面也是一个"@"符号和其参数的字节数,格式为@functionname@number。

编辑本段设置方法

  1 可以直接在代码中写 __cdecl 等调用约定  2 在MS-VC++6.0中,调用约定也可以通过工程设置:Setting...\C/C++ \Code Generation项进行选择,缺省状态为__cdecl。名字修饰约定。
原创粉丝点击