参考链接
- http://c.biancheng.net/cpp/u/dll/
DLL 编写
// filename: main.c
#include <windows.h>
#include <stdio.h>
_declspec(dllexport) int add(int a, int b) {
return a + b;
}
_declspec(dllexport) int sub(int a, int b) {
return a - b;
}
BOOL WINAPI DllMain(
HINSTANCE hinstDLL, // handle to DLL module
DWORD fdwReason, // reason for calling function
LPVOID lpReserved) // reserved
{
// Perform actions based on the reason for calling.
switch (fdwReason)
{
case DLL_PROCESS_ATTACH:
// Initialize once for each new process.
// Return FALSE to fail DLL load.
printf("dll is loaded!\n");
break;
case DLL_THREAD_ATTACH:
// Do thread-specific initialization.
break;
case DLL_THREAD_DETACH:
// Do thread-specific cleanup.
break;
case DLL_PROCESS_DETACH:
// Perform any necessary cleanup.
break;
}
return TRUE; // Successful DLL_PROCESS_ATTACH.
}
// 注意:工程名为dllDemo,所以编译后会生成dllDemo.dll和dllDemo.lib两个文件(这两个文件很重要)
显式加载
// 什么是显式加载?
// 显式加载又叫运行时加载,指主程序在运行过程中需要DLL中的函数时再加载。显式加载是将较大的程序分开加载的,程序运行时只需要将主程序载入内存,软件打开速度快,用户体验好。
// filename:main.c
#include<stdio.h>
#include<stdlib.h>
#include<windows.h>
typedef int (*FUNADDR)(int, int);
int main() {
int a = 10, b = 5, x;
HINSTANCE dllDemo = LoadLibrary(L"E:\\CProjects\\DllPractice\\x64\\Debug\\DllPractice.dll");
FUNADDR add, sub;
if (dllDemo) {
add = (FUNADDR)GetProcAddress(dllDemo, "add");
sub = (FUNADDR)GetProcAddress(dllDemo, "sub");
}
else {
x = GetLastError();
printf("error code: %d\n", x);
exit(1);
}
printf("a+b=%d\n", add(a, b));
printf("a-b=%d\n", sub(a, b));
return 0;
}
// 注意:编译时不需要dllDemo.lib文件,直接独立编译。
隐式加载
// 什么是隐式加载?
// 隐式加载又叫载入时加载,指在主程序载入内存时搜索DLL,并将DLL载入内存。隐式加载也会有静态链接库的问题,如果程序稍大,加载时间就会过长,用户不能接受。
// filename: main.c
#include <stdio.h>
#include "dllDemo.h"
int main(void) {
int a = 10, b = 5;
printf("a + b = %d\n", add(a, b));
return 0;
}
// dllDemo.h
#ifndef _DLLDEMO_H
#define _DLLDEMO_H
#pragma comment(lib, "dllDemo.lib")
_declspec(dllexport) int add(int, int);
#endif
// 注意:编译的时候需要dllDemo.lib文件放在一起进行编译。