• 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;
    }
    
  • 相关阅读:
    java web报错The superclass "javax.servlet.http.HttpServlet" was not found on the Java Build Path
    在cmd下执行mvn help:system 报错
    win10安装mysql5.7
    centos7装单机hadoop2.7.3
    win10装jdk
    oracle中批量修改年份和月份,但不修改时分秒
    Python 正则匹配网页内的IP地址及端口号
    python 爬取网页内的代理服务器列表(需调整优化)
    python 爬取百度url
    Python 爬取SeeBug poc
  • 原文地址:https://www.cnblogs.com/0x7e/p/13808620.html
Copyright © 2020-2023  润新知