关于我想要编写dll文件这件事

0x1前言

首先我们要用C、C++编写dll,肯定是需要一个合适的编写软件,什么!?你不知道什么是dll,那你这有必要去看看我得上一篇《初识Windows APi》了虽然篇幅不长,但是可以让你对dll有个大致得印象,由于本人用的CLion 2019的版本的,至于为什么不用VS,因为里面配置过于繁琐,很不友好,CLion安装包以及破解 群文件都有,可以去下载直接使用。话不多说,进入今天的正题:


利用C、C++简单的编写一个DLL文件

::: tip 开发环境:CLion 2019.3.3 编译器:WinGW64 ::: 打开CLion 新建一个 C Library项目DLL image library.c默认代码 image 按下Ctrl+F9编译,右侧生成libDLL.dll文件 image

调用dll

新建一个项目 untitled1 ,在untitled1下创建一个lib目录,存放刚刚生成的dll文件, image 配置CMakeLists.txt:

1cmake_minimum_required(VERSION 3.15) 2#项目名 3project(untitled1 ) 4 5set(CMAKE_C_STANDARD 99) 6 7#新增:指项目根目录下的lib目录 8link_directories(lib) 9 10add_executable(untitled1 main.c ) 11 12#新增:目标链接的dll文件 13target_link_libraries(untitled1 libDLL.dll) 14

配置main.c:

1#include <stdio.h> 2void hello(); 3int main() { 4 printf("下面是一个dll的调用"); 5 hello(); 6 getchar(); 7 return 0; 8}

配置Configurations: 将lib目录的绝对路径填入(如用群里的中文插件可能导致这里显示异常) image 然后编译运行结果如下: image 到这里只是用实操演示一下dll的由来,只能对编写dll有一个认识,当然无法准确的理解,那么请继续往下看


详解

这里介绍一下dll动态链接库的核心入口函数 DLLMain() 跟exe有个main或者WinMain入口函数一样,DLL也有一个入口函数,就是DllMain。 以"DllMain"为关键字,来看看MSDN帮助文档怎么介绍这个函数的。

The DllMain function is an optional method of entry into a dynamic-link library (DLL) 。 (简要翻译:对于一个Dll模块,DllMain函数是可选的。)这句话很重要,很多初学者可能都认为一个动态链接库肯定要有DllMain函数。其实不然,像很多仅仅包含资源信息的DLL是没有DllMain函数的。

1#include <windows.h> 2_Bool WINAPI DllMain(HINSTANCE hinstDLL, // handle to DLL module 3 DWORD fdwReason, // reason for calling function 4 LPVOID lpReserved ) // reserved 5{ 6 // Perform actions based on the reason for calling. 7 switch( fdwReason) 8 { 9 case DLL_PROCESS_ATTACH: 10 // Initialize once for each new process. 11 // Return FALSE to fail DLL load. 12 break; 13 14 case DLL_THREAD_ATTACH: 15 // Do thread-specific initialization. 16 break; 17 18 case DLL_THREAD_DETACH: 19 // Do thread-specific cleanup. 20 break; 21 22 case DLL_PROCESS_DETACH: 23 // Perform any necessary cleanup. 24 break; 25} 26 return TRUE; // Successful DLL_PROCESS_ATTACH. 27}

因为返回类型是布尔类型,所以最后要return true hinstDLL参数:DLL模块的句柄。该值是DLL的基地址;

fdwReason [in]参数:指明了DLL被调用的原因,可以有以下4个取值: ::: tip

1. DLL_PROCESS_ATTACH: 当DLL被进程 <第一次>调用时,导致DllMain函数被调用, 同时ul_reason_for_call的值为DLL_PROCESS_ATTACH, 如果同一个进程后来再次调用此DLL时,操作系统只会增加DLL的使用次数, 不会再用DLL_PROCESS_ATTACH调用DLL的DllMain函数。

2.DLL_PROCESS_DETACH: 当DLL被从进程的地址空间解除映射时,系统调用了它的DllMain,传递的ul_reason_for_call值是DLL_PROCESS_DETACH。 ★如果进程的终结是因为调用了TerminateProcess,系统就不会用DLL_PROCESS_DETACH来调用DLL的DllMain函数。这就意味着DLL在进程结束前没有机会执行任何清理工作。

3.DLL_THREAD_ATTACH: 当进程创建一线程时,系统查看当前映射到进程地址空间中的所有DLL文件映像,并用值DLL_THREAD_ATTACH调用DLL的DllMain函数。 新创建的线程负责执行这次的DLL的DllMain函数, 只有当所有的DLL都处理完这一通知后,系统才允许线程开始执行它的线程函数。

4.DLL_THREAD_DETACH: 如果线程调用了ExitThread来结束线程(线程函数返回时,系统也会自动调用ExitThread),系统查看当前映射到进程空间中的所有DLL文件映像,并用DLL_THREAD_DETACH来调用DllMain函数,通知所有的DLL去执行线程级的清理工作。 ::: ::: warning ★如果线程的结束是因为系统中的一个线程调用了TerminateThread,系统就不会用值DLL_THREAD_DETACH来调用所有DLL的DllMain函数。 ::: lpReserved参数:系统保留,不让我们利用,目前没什么意义。 不过关于lPReserved参数,看到一位网友是这样说的:

“lpvReserved:为零表示隐式载入,不为零表示显示载入 不是没有什么意义”,我还没有深究,暂做参考

点赞
收藏

评论区

加载中...

相关推荐

MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1

文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s

Oracle 分组与拼接字符串同时使用

SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(

MySQL部分从库上面因为大量的临时表tmp_table造成慢查询

背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_

皕杰报表之UUID

​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为

手写Java HashMap源码

HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22

2020年前端实用代码段,为你的工作保驾护航

有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )