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;
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM