c语言创建dll以及使用

0x01. declspec(dllexport)创建导出dll

笔者这边使用vs 2015,但是性质都一样的

新建项目 -》 Win32控制台应用程序 -》 dll

这时候就创建了一个项目

我们在头文件和源文件创建下文件

头文件 test.h

extern "C" _declspec(dllexport) int Plus(int x, int y);
extern "C" _declspec(dllexport) int Sub(int x, int y);
extern "C" _declspec(dllexport) int Mul(int x, int y);
extern "C" _declspec(dllexport) int Div(int x, int y);

说明:

1、extern 表示这是个全局函数,可以供各个其他的函数调用;

2、"C" 按照C语言的方式进行编译、链接
__declspec(dllexport)告诉编译器此函数为导出函数;

3、也可以在int类型后面加个调用约定,决定外平栈还是内平栈
详细的调用约定和dll之间的关系可以查看这篇文章:https://blog.csdn.net/qq_34696097/article/details/89639184

源文件:main.cpp

#include "test.h"

int Plus(int x, int y)
{
	return x + y;
}
int Sub(int x, int y)
{
	return x - y;
}
int Mul(int x, int y)
{
	return x*y;
}
int Div(int x, int y)
{
	return x / y;
}

0x02. .def创建导出dll

test.h:

int Plus(int x, int y);
int Sub(int x, int y);
int Mul(int x, int y);
int Div(int x, int y);

main.cpp

#include "test.h"

int Plus(int x, int y)
{
	return x + y;
}
int Sub(int x, int y)
{
	return x - y;
}
int Mul(int x, int y)
{
	return x*y;
}
int Div(int x, int y)
{
	return x / y;
}
EXPORTS	
	
Plus   	@12
Sub		@15 NONAME
Mul    	@13
Div    	@16

//函数名 12(这是导出序号,是12,可以随便写)
//NONAME 意思是说只有序号,没有名字
//可以通过这种方式隐藏起来

0x03. 方式一:隐式调用DLL

步骤1:将 *.dll *.lib 放到工程目录下面

步骤2:将 #pragma comment(lib,"DLL名.lib") 添加到调用文件中

步骤3:加入函数的声明

extern "C" __declspec(dllimport)  int Plus(int x, int y);
extern "C" __declspec(dllimport)  int Sub(int x, int y);
extern "C" __declspec(dllimport)  int Mul(int x, int y);
extern "C" __declspec(dllimport)  int Div(int x, int y);

注意一些差别,上面的是__declspec(dllexport),而我们使用的时候是用 __declspec(dllimport)
意味着引用,导入的意思,就会调用这个函数了
extern "C" :调用的时候把这一串删掉也没事,但是为了养成好习惯,还是留着吧

0x04. 方式二:显示调用

步骤1://定义函数指针

      typedef int( *lpPlus)(int, int);
      typedef int( *lpSub)(int, int);
      typedef int( *lpMul)(int, int);
      typedef int( *lpDiv)(int, int);

步骤2://声明函数指针变量

      lpPlus myPlus;
      lpSub mySub;
      lpMul myMul;
      lpDiv myDiv;

步骤3://动态加载dll到内存中
HINSTANCE hModule = LoadLibrary(L"DllTest.dll");

步骤4://获取函数地址一

      myPlus = (lpPlus)GetProcAddress(hModule, "Plus");
      mySub = (lpSub)GetProcAddress(hModule, "Sub");
      myMul = (lpMul)GetProcAddress(hModule, "Mul");
      myDiv = (lpDiv)GetProcAddress(hModule, "Div");
  //获取函数地址二(例如之前如果使用了__stdcall的话就是另外一种方式)
      myPlus = (lpPlus)GetProcAddress(hModule, "_Plus@8");
      mySub = (lpSub)GetProcAddress(hModule, "_Sub@8");
      myMul = (lpMul)GetProcAddress(hModule, "_Mul@8");
      myDiv = (lpDiv)GetProcAddress(hModule, "_Div@8");
  函数名前面有个下划线,然后@后面的8,8就是因为有两个int,一个int是4字节,所以会是8

步骤5://调用函数

      int a = myPlus(10, 2);
      int b = mySub(10, 2);
      int c = myMul(10, 2);
      int d = myDiv(10, 2);


源代码:

#include <stdio.h>
#include <windows.h>

typedef int( *lpPlus)(int, int);
typedef int( *lpSub)(int, int);
typedef int( *lpMul)(int, int);
typedef int( *lpDiv)(int, int);



int main()
{
	lpPlus myPlus;
	lpSub mySub;
	lpMul myMul;
	lpDiv myDiv;


	HINSTANCE   hModule = LoadLibrary(L"DllTest.dll");

	myPlus = (lpPlus)GetProcAddress(hModule, "Plus");
	mySub = (lpSub)GetProcAddress(hModule, "Sub");
	myMul = (lpMul)GetProcAddress(hModule, "Mul");
	myDiv = (lpDiv)GetProcAddress(hModule, "Div");

	int x = myPlus(10, 20);
	printf("%d", x);

	return 0;
}
原文地址:https://www.cnblogs.com/0x7e/p/13808620.html