VC如何动态调用DLL里的函数?

wenyongjie 2004-07-26 11:30:01
有例子最佳
...全文
1100 4 打赏 收藏 转发到动态 举报
写回复
用AI写文章
4 条回复
切换为时间正序
请发表友善的回复…
发表回复
kpld8888 2004-07-27
  • 打赏
  • 举报
回复
我有,qq:101059899,email:kpld@163.com
qqhuangshen 2004-07-27
  • 打赏
  • 举报
回复
综合以上例子,有两种调用动态连接库中的函数的方法


1.通过引入库:

利用Visual C++提供的IMPLIB工具为动态连接库生成引入库,为引入库设计一个头文件:

#ifndef _MYMATH_H

#define _MYMATH_H

extern “C”

{

int Summary(int n);

int Factorial(int n);

}

#endif

将该头文件包含在使用动态连接库的源文件中,连接应用程序时会连接上该引入库。这样,应用程序就可以象使用静态连接库一样自由的使用动态连接库中的函数了。注意要把动态连接库拷贝到应用程序可执行文件所在的目录(\TEST\DEBUG)下。

这是一种常用的方法。实际上,应用程序就是通过这种方式访问Windows的API函数的。Windows为其内核动态连接库生成引入库并提供了头文件。应用程序在编译时将引入库的信息带入可执行文件中,在运行时通过引入库信息访问API函数。

2. 直接指定库和函数地址

这种方式适合于一些提供文件格式转换等服务的动态连接库。比如,一个程序带有多个动态连接库,分别用于访问JPG、BMP、GIF等多种图像文件格式,这些动态连接库提供了相同的库函数接口。此时,无法使用引入库方式指定库函数。可以采用下面的方法来解决这个问题。

HANDLE hLibrary;

FARPROC lpFunc;

int nFormat;

if(nFormat==JPEG)//如果是JPEG格式,装入JPEG动态连接库

{

hLibrary=LoadLibrary(“JPEG.DLL”);

}

else//是GIF格式

hLibrary= LoadLibrary(“GIF.DLL”);

if(hLibrary>=32)

{

lpFunc=GetProcAddress(hLibrary,”ReadImage”);

if(lpFunc!=(FARPROC)NULL)

(*lpFunc)((LPCTSTR)strFileName);

FreeLibrary(hLibrary);

}

LoadLibrary函数装入所需的动态连接库,并返回库的句柄。如果句柄小于32,则载入库失败,错误含义参见有关手册。GetProcAddress函数使用函数名字取得函数的地址。利用该函数地址,就可以访问动态连接库的函数了。
qqhuangshen 2004-07-27
  • 打赏
  • 举报
回复
现在,来使用刚才生成的动态连接库。。首先,把mymaths\debug目录下的mymaths.dll拷贝到test\debug目录下。test程序运行时,会在该目录下搜索动态连接库文件。然后修改testdlg.h,在其中加入一个函数LoadDLL()的声明,LoadDLL用于载入动态连接库。

class CTestDlg : public CDialog

{

// Construction

public:

CTestDlg(CWnd* pParent = NULL); // standard constructor

protected:

void LoadDLL();

//......

}

然后修改testdlg.cpp,修改后如清单9.5。

清单95. TestDlg.cpp文件

// TestDlg.cpp : implementation file

//

#include "stdafx.h"

#include "Test.h"

#include "TestDlg.h"

//#include "mymath.h" //注释掉mymath.h头文件

#ifdef _DEBUG

#define new DEBUG_NEW

#undef THIS_FILE

static char THIS_FILE[] = __FILE__;

#endif

//The instance of the Mymaths.DLL library

HINSTANCE ghMathsDLL=NULL;

//declare the Summary() function from the Mymaths.DLL libray.

typedef int (*SUMMARY)(int);

SUMMARY Summary;

//declare the Factorial() function from

//the Mymaths.DLL library.

typedef int (*FACTORIAL)(int);

FACTORIAL Factorial;

/////////////////////////////////////////////////////////////////////////////

// CAboutDlg dialog used for App About

class CAboutDlg : public CDialog

{

//...

};

//CAboutDlg的一些成员函数定义

//CTestDlg的一些成员函数定义

void CTestDlg::OnSum()

{

// TODO: Add your control notification handler code here

LoadDLL();

int nSum=Summary(10);

CString sResult;

sResult.Format("Sum(10)=%d",nSum);

AfxMessageBox(sResult);

}

void CTestDlg::OnFactorial()

{

// TODO: Add your control notification handler code here

LoadDLL();

int nFact=Factorial(10);

CString sResult;

sResult.Format("10!=%d",nFact);

AfxMessageBox(sResult);

}

void CTestDlg::LoadDLL()

{

//如果DLL已经载入,则返回

if(ghMathsDLL!=NULL)

{

return;

}

//载入Mymaths.DLL文件.

ghMathsDLL=LoadLibrary("mymaths.DLL");

//如果载入DLL失败,提示用户

if(ghMathsDLL==NULL)

{

AfxMessageBox("Cannot load DLL file!");

}

//获得DLL中Summary函数的地址

Summary=(SUMMARY)GetProcAddress(ghMathsDLL,"Summary");

//获得DLL中Factorial函数的地址

Factorial=(FACTORIAL)GetProcAddress(ghMathsDLL,"Factorial");

}

 

在testdlg.cpp文件开头,加入:

//The instance of the Mymaths.DLL library

HINSTANCE ghMathsDLL=NULL;

//declare the Summary() function from the Mymaths.DLL libray.

typedef int (*SUMMARY)(int);

SUMMARY Summary;

//declare the Factorial() function from

//the Mymaths.DLL library.

typedef int (*FACTORIAL)(int);

FACTORIAL Factorial;


qqhuangshen 2004-07-27
  • 打赏
  • 举报
回复
譬如这样创建了如下DLL文件。最简单的求和函数和阶乘函数
文件1:mymaths.cpp

////////////////////////////

//mymaths.cpp

//

//a maths API DLL.

//

///////////////////////////

#include<windows.h>

//Declare the DLL functions prototypes

int Summary(int);

int Factorial(int);

//////////////////////////

//DllEntryPoint():The entry point of the DLL

//

/////////////////////////

BOOL WINAPI DLLEntryPoint(HINSTANCE hDLL,DWORD dwReason,

LPVOID Reserved)

{

switch(dwReason)

{

case DLL_PROCESS_ATTACH:

{

//一些初始化代码

break;

}

case DLL_PROCESS_DETACH:

{

//一些用于清理的代码

break;

}

}

return TRUE;

}

int Summary(int n)

{

int sum=0;

int i;

for(i=1;i<=n;i++)

{

sum+=i;

}

return sum;

}

int Factorial(int n)

{

int Fact=1;

int i;

for(i=1;i<=n;i++)

{

Fact=Fact*i;

}

return Fact;

}

文件2:mymaths.def

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;Mymaths.DEF

;

;The DEF file for the Mymaths.DLL DLL.

;

LIBRARY mymaths

CODE PRELOAD MOVEABLE DISCARDABLE

DATA PRELOAD SINGLE

EXPORTS

;The names of the DLL functions

Summary

Factorial

在文件mymaths.cpp开头,声明了动态连接库所包含的两个函数:Summary和Factorial。接着是DllEntryPoint()函数的定义。DllEntryPoint()顾名思义是动态连接库的入口,应用程序通过该入口访问动态连接库提供的服务。DllEntryPoint()主体是一个switch/case语句:

switch(dwReason)

{

case DLL_PROCESS_ATTACH:

{

//一些初始化代码

break;

}

case DLL_PROCESS_DETACH:

{

//一些用于清理的代码

break;

}

}


15,472

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 进程/线程/DLL
社区管理员
  • 进程/线程/DLL社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧