//mathlib.h
#ifndef _MYMATH_H
#define _MYMATH_H
extern "C" int _declspec(dllexport) Summary(int n);
extern "C" int _declspec(dllexport) Factorial(int n);
#endif
//mathlib.cpp
#include "stdafx.h"
#include "mathlib.h"
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;
}
以上编译成常规DLL,用于下面:
// dllcall1.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <Windows.h>
#include <iostream>
typedef int (*lpFun)(int);//定义函数指针类型
int _tmain(int argc, _TCHAR* argv[])
{
HINSTANCE hDll;//DLL句柄
lpFun SumFun,FactorialFun;//函数指针
hDll=LoadLibrary(_T("dllCall.dll"));//载入指定的动态链接库
if(hDll != NULL)
{
SumFun = (lpFun)GetProcAddress(hDll,"Summary");//GetProcAddress()函数返回类型为FARPROC,强制转换成lpFun
if(SumFun!=NULL)
{
int result=SumFun(10);
std::cout<<"Sum(10)="<<result<<std::endl;
}
FactorialFun=(lpFun)GetProcAddress(hDll,"Factorial");
if(FactorialFun!=NULL)
{
int result=FactorialFun(10);
std::cout<<"10!="<<result<<std::endl;
}
FreeLibrary(hDll);//释放指定的动态链接库
}
return 0;
}
常规DLL的优点有以下几方面:
客户程序不必是一个MFC应用程序。它只需要能调用C函数即可,既可以是MFC应用程序,也可以是Delphi或Visual Basic应用程序。
在常规DLL的内部可以使用C++类,然后只导出C函数的包装器。这样,对内部的C++类的任何修改都不会影响到调用它的应用程序或DLL。
在主函数中定义了一个DLL HINSTANCE句柄实例hDll,通过Win32 API函数LoadLibrary动态加载了DLL模块。在主函数中通过Win32 API函数GetProcAddress()得到了所加载DLL模块中函数的地址,并使用函数指针变量保存。这样就可以使用函数指针调用DLL中导出的函数。最后,在应用项目中使用完DLL后,应立即调用FreeLibrary()函数释放已经加载的DLL模块。
在加载DLL时,Windows必须找到实际的物理文件。Windows在加载DLL时按以下顺序寻找文件。
1-当前应用程序的可执行模块所在的目录
2-当前目录
3-Windows系统目录
4-Windows目录
5-PATH环境变量中列出的目录