静态链接库
OD查看模块,没有 TestStaticLib.lib 模块
OD 查看汇编,找到Plus方法,发现 静态链接库编译在调用它的exe中,并没有实现真正的模块化
Plus方法
代码
编译lib
stdafx.h
#ifndef __LIB_H__
#define __LIB_H__
int Plus(int x,int y);
int Sub(int x,int y);
int MutiPl(int x,int y);
int Divide(int x,int y);
#endif
stdafx.cpp
#include "stdafx.h"
int Plus(int x,int y)
{
return x+y;
}
int Sub(int x,int y)
{
return x-y;
}
int MutiPl(int x,int y)
{
return x*y;
}
int Divide(int x,int y)
{
if(y!=0)
return x/y;
return 0;
}
把.lib文件放在新工程目录下,调用lib
main.cpp
#include <stdio.h>
#include "stdafx.h"
#pragma comment(lib,"TestStaticLib.lib")
int main(int argc, char* argv[])
{
printf("%d
",Plus(1,2));
return 0;
}
动态链接库
关键字解读
extern
C :按C编译,编译后的函数名用Depends打开如下:
__declspec(dllexport)告诉编译器此函数为导出函数;
lib代码
MyDll.h
#if !defined(AFX_STDAFX_H__6DE6F869_445D_43BA_A4B8_8DD48F71F80A__INCLUDED_)
#define AFX_STDAFX_H__6DE6F869_445D_43BA_A4B8_8DD48F71F80A__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
extern "C" _declspec(dllexport) __stdcall int Plus(int x,int y); //extern :全局函数,可以供各个函数调用
extern "C" _declspec(dllexport) __stdcall int Sub(int x,int y); //C 按照C语言方式进行编译、链接
extern "C" _declspec(dllexport) __stdcall int Mul(int x,int y); //_declspec(dllexport) 告诉编译器这是导出函数
extern "C" _declspec(dllexport) __stdcall int Div(int x,int y);
#endif
MyDll.cpp
#if !defined(AFX_STDAFX_H__6DE6F869_445D_43BA_A4B8_8DD48F71F80A__INCLUDED_)
#define AFX_STDAFX_H__6DE6F869_445D_43BA_A4B8_8DD48F71F80A__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
extern "C" _declspec(dllexport) __stdcall int Plus(int x,int y); //extern :全局函数,可以供各个函数调用
extern "C" _declspec(dllexport) __stdcall int Sub(int x,int y); //C 按照C语言方式进行编译、链接
extern "C" _declspec(dllexport) __stdcall int Mul(int x,int y); //_declspec(dllexport) 告诉编译器这是导出函数
extern "C" _declspec(dllexport) __stdcall int Div(int x,int y);
#endif
两种调用方式
方式一:隐式连接
步骤1:将 *.dll *.lib 放到工程目录下面
步骤2:将 #pragma comment(lib,"DLL名.lib") 添加到调用文件中
步骤3:加入函数的声明
extern "C" __declspec(dllimport) __stdcall int Plus (int x,int y);
extern "C" __declspec(dllimport) __stdcall int Sub (int x,int y);
extern "C" __declspec(dllimport) __stdcall int Mul (int x,int y);
extern "C" __declspec(dllimport) __stdcall int Div (int x,int y);
说明:
__declspec(dllimport)告诉编译器此函数为导入函数;
代码
StdAx.h
#if !defined(AFX_STDAFX_H__2846F71E_C0E2_4634_94E9_857285842867__INCLUDED_)
#define AFX_STDAFX_H__2846F71E_C0E2_4634_94E9_857285842867__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
extern "C" __declspec(dllimport) __stdcall int Plus (int x,int y);
extern "C" __declspec(dllimport) __stdcall int Sub (int x,int y);
extern "C" __declspec(dllimport) __stdcall int Mul (int x,int y);
extern "C" __declspec(dllimport) __stdcall int Div (int x,int y);
#endif // !defined(AFX_STDAFX_H__2846F71E_C0E2_4634_94E9_857285842867__INCLUDED_)
TestLib.cpp
// StaticLib.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <stdio.h>
#pragma comment(lib,"TestDynLib2.lib")
int main(int argc, char* argv[])
{
printf("%d
",Plus(1,2));
return 0;
}
方式二:显示链接
步骤1: //定义函数指针
typedef int (__stdcall *lpPlus)(int,int);
typedef int (__stdcall *lpSub)(int,int);
typedef int (__stdcall *lpMul)(int,int);
typedef int (__stdcall *lpDiv)(int,int);
步骤2: //声明函数指针变量
lpPlus myPlus;
lpSub mySub;
lpMul myMul;
lpDiv myDiv;
步骤3: //动态加载dll到内存中
HINSTANCE hModule = LoadLibrary("DllDemo.dll");
步骤4: //获取函数地址
myPlus = (lpPlus)GetProcAddress(hModule, "_Plus@8");
mySub = (lpSub)GetProcAddress(hModule, "_Sub@8");
myMul = (lpMul)GetProcAddress(hModule, "_Mul@8");
myDiv = (lpDiv)GetProcAddress(hModule, "_Div@8");
步骤5: //调用函数
int a = myPlus(10,2);
int b = mySub(10,2);
int c = myMul(10,2);
int d = myDiv(10,2);
特别说明:
Handle 是代表系统的内核对象,如文件句柄,线程句柄,进程句柄。
HMODULE 是代表应用程序载入的模块
HINSTANCE 在win32下与HMODULE是相同的东西 Win16 遗留
HWND 是窗口句柄
其实就是一个无符号整型,Windows之所以这样设计有2个目的:
1、可读性更好
2、避免在无意中进行运算
代码
TestLib.cpp
// StaticLib.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <stdio.h>
#include <windows.h>
typedef int (__stdcall *lpPlus)(int,int);
typedef int (__stdcall *lpSub)(int,int);
typedef int (__stdcall *lpMul)(int,int);
typedef int (__stdcall *lpDiv)(int,int);
int main(int argc, char* argv[])
{
lpPlus myPlus;
lpSub mySub;
lpMul myMul;
lpDiv myDiv;
HINSTANCE hModule = LoadLibrary("TestDynLib2.dll");
myPlus = (lpPlus)GetProcAddress(hModule, "_Plus@8");
mySub = (lpSub)GetProcAddress(hModule, "_Sub@8");
myMul = (lpMul)GetProcAddress(hModule, "_Mul@8");
myDiv = (lpDiv)GetProcAddress(hModule, "_Div@8");
int a = myPlus(10,2);
int b = mySub(10,2);
int c = myMul(10,2);
int d = myDiv(10,2);
printf("%d,%d,%d,%d
",a,b,c,d);
return 0;
}