创建DLL

Dll是动态链接库的缩写,可以作为附加代码动态映射到进程的地址空间中。

动态库的一般创建方法如下

方法1、使用 __declspec(dllexport)  方式导出

一般的框架如下

//头文件

#ifndef __MAIN_H__

#define __MAIN_H__

#include <windows.h>

#ifdef MAIN_DLL

#define DLL_EXPORT __declspec(dllexport)

#else

#define DLL_EXPORT __declspec(dllimport)

//在导入dll中的函数的时候,__declspec(dllimport)关键字不是必须的

//可以直接用extern 修饰 ,但是,如果编译器提前知道某一函数是从dll

//中导入的话,会产生略微高效的代码,所以建议使用该关键字

#endif

#ifdef __cplusplus

extern "C"  //是否使用的是C++,如果使用的是C++ , 则告诉编译器不要改编函 //数名

{

#endif

void DLL_EXPORT SomeFunction(const LPCSTR sometext);

//在此处添加需要导出的函数的声明

//声明的形式如下

// type  DLL_EXPORT funcName(  arguments  );

#ifdef __cplusplus

}

#endif

#endif // __MAIN_H__

// 源文件:

#include "main.h"

//一个导出函数的创建

void DLL_EXPORT simpleFunc()

{

MessageBoxA(0,  "DLL", "DLL Message", MB_OK | MB_ICONINFORMATION);

}

extern "C" DLL_EXPORT BOOL APIENTRY DllMain(

HINSTANCE hinstDLL, //当前载入的dll的模块句柄

DWORD fdwReason, //DllMain函数被调用的原因(四种)

LPVOID lpvReserved)//保留参数,现在无用

{

switch (fdwReason)

{

case DLL_PROCESS_ATTACH://dll在进程中第一次被载入

break;

case DLL_PROCESS_DETACH://dll从进程地址空间中被移除

break;

case DLL_THREAD_ATTACH://当进程中有新线程创建的时候

break;

case DLL_THREAD_DETACH://当进程中某一线程终止的时候

break;

}

return TRUE; //如果成功返回TRUE , 失败返回false

}

方法2、

使用 DEF 文件 。

为什么要使用def文件呢???

有两点:

1、使用def文件可以实现序号导出

2、使用ms的编译器的时候,当函数的调用约定为 __stdcall(WINAPI)的时候,

编译器会对 C函数名进行改编,改编的规则是在函数名前加一个前缀 ,在函数名后加一个 特殊的后缀 , 前缀就是一个下划线 “_” , 而后缀则是 一个 “@”符号加上一个数字 , 该数字表示函数参数的总字节数

例如

LPVOID  funcName ( INT iArgument1,INT iArgument2,PVOID pArgument3 );

函数名为 funcName

改编后的函数名为 _funcName@12

12 = sizeof(INT)*2 + sizeof(PVOID) ;

而是用def文件的时候,当dll用于其它厂家的编译器的时候,就不会遇到函 数名改编的问题 (例如我现在是用的 code blocks),是用原始函数名就可以

导出

使用Def方式导出函数的时候,大致使用的也是上述的代码 ,不过在头文件中

#define DLL_EXPORT __declspec(dllexport)  这一句代码应该改为

#define DLL_EXPORT , 即取消 该关键字的使用 。

作为替代

现在来新建一个 *.def  文件  文件命名为  xxx.def  名称和工程名一致。

现在来书写 *.def 文件

*.def  文件常用的语法也不复杂 , 常用到的关键字就两个 LIBARY  和 EXPORTS

//*.def 文件

LIBRARY  dLLName

EXPORTS

exportFuncName  [@ordinal]/*导出序号*/  [NONAME]/*仅以序号方式导出*/

注:当指定NONAME的时候,dll中不包含函数名的字符串 , 函数仅仅以序号的方式导出 , 当导出函数很多,而且以序号方式导出的时候,有利于减小dll的体积

此时,调用 GetProcAddress 的方法是 :

GetProcAddress( handle ,  MAKEINTRESOURCE(ordinal) );

//利用 MAKEINTRESOURCE 这个宏

//#define MAKEINTRESOURCE MAKEINTRESOURCEA

// #define MAKEINTRESOURCEA(i) (LPSTR)((DWORD)((WORD)(i)))

更过def文件的规则此处不列出,可到以下网址查看

http://msdn.microsoft.com/zh-cn/library/28d6s79h(v=vs.80).aspx

3、还有一种方法:是用 export 开关,同样是用 __declspec(dllexport) 关键字, 但是在头文件

的开头处加上如下语句:

#pragma comment(linker, “/export:funcName = _funcName@12”)

很显然,这种方法非常烦,不建议使用

windows编程:创建DLL的更多相关文章

  1. C/C++:Windows编程—调用DLL程序的2种方法(转载)

    文章为转载,原文出处https://blog.csdn.net/qq_29542611/article/details/86618902 前言先简单介绍下DLL.DLL:Dynamic Link Li ...

  2. [Windows编程] 开发DLL必读《Best Practices for Creating DLLs》

    开发DLL的时候,需要十分注意 DllMain 函数,因为在多线程环境下DLLMain里面的代码很容易引发线程死锁. 这篇MSDN文章<Best Practices for Creating D ...

  3. windows下编写dll

    dll的优点 简单的说,dll有以下几个优点: 1) 节省内存.同一个软件模块,若是以源代码的形式重用,则会被编译到不同的可执行程序中,同时运行这些exe时这些模块的二进制码会被重复加载到内存中.如果 ...

  4. windows编程 进程的创建销毁和分析

    Windows程序设计:进程 进程是一个具有一定独立功能的程序关于某个数据集合的一次运行活动,在Windows编程环境下,主要由两大元素组成: • 一个是操作系统用来管理进程的内核对象.操作系统使用内 ...

  5. Windows编程总结之 DLL

    +-- 版本 --+-- 编辑日期 --+-- 作者 -------------+ | V1. | | yin_caoyuan@.com | +----------+--------------+-- ...

  6. 【Windows编程】系列第六篇:创建Toolbar与Statusbar

    上一篇我们学习了解了如何使用Windows GDI画图,该应用程序都是光光的静态窗口,我们使用Windows应用程序,但凡稍微复杂一点的程序都会有工具栏和状态栏,工具栏主要用于一些快捷功能按钮.比如典 ...

  7. 【Windows编程】系列第七篇:Menubar的创建和使用

    上一篇我们学习了利用windows API创建工具栏和菜单栏,与上一篇紧密联系的就是菜单栏,菜单栏是一个大多数复杂一些的Windows应用程序不可或缺的部分.比如下图就是Windows自带的记事本的菜 ...

  8. 【Windows编程】系列第三篇:文本字符输出

    上一篇我们展示了如何使用Windows SDK创建基本控件,本篇来讨论如何输出文本字符. 在使用Win32编程时,我们常常要输出文本到窗口上,Windows所有的文本字符或者图形输出都是通过图形设备接 ...

  9. MFC-01-Chapter01:Hello,MFC---1.1 Windows 编程模型

    1.1 Windows编程模型 为传统的操作系统编写的程序使用的是过程化模型,即程序从头到尾按顺序执行.例如C程序,从main函数入口开始执行,中间调用不同的函数一直到程序结束返回,这种过程是程序本身 ...

随机推荐

  1. bash color

    紫色:300A24 黄色:C4A000 Tango 紫色: 200213

  2. VS2012+EF6+Mysq

    为了学习ORM,选择了EntityFramework,经历了三天两夜的煎熬,N多次错误,在群里高手的帮助下,终于成功,现在将我的心路历程记录下来,一是让自己有个记录,另外就是让其它人少走些弯路. 我的 ...

  3. Linux中切换用户变成-bash4.1-$的解决方法【转】

    转自 Linux中切换用户变成-bash4.1-$的解决方法 - xia_xia的博客 - 博客频道 - CSDN.NEThttp://blog.csdn.net/xia_xia0919/articl ...

  4. MySQL-测试卷一

    MySQL-测试卷一 一.单项选择题 1 下面不属于Msql数据库特点的是(  ) A. 免费使用  B.不能跨平台  C.开源软件  D.功能强大 2 定义表的一个字段, 要求能表示4位整数,2位小 ...

  5. .htaccess重写URL讲解

    使用ThinkPHP和Laravel等框架的都知道,所以的请求都需要经过index.php文件入口,无论你的URI是什么. 当然除了访问的是静态文件或者访问路径的文件真实存在,例如你访问xxx.com ...

  6. 个人linux简单笔记,随时更新

    vim显示行数 :set nu 查找文件 find /home -name config.txt 重命名文件或者文件夹 mv a b centos中phpize的安装 yum install php- ...

  7. 状压dp Codeforces Beta Round #8 C

    http://codeforces.com/contest/8/problem/C 题目大意:给你一个坐标系,给你一个人的目前的坐标(该坐标也是垃圾桶的坐标),再给你n个垃圾的坐标,这个人要捡完所有的 ...

  8. QML之使用Loader加载QML组件

    呵呵,今晚是边看<裸婚时代>边敲代码,那电影看得...!钱真他妈不是个东西. 盼望Meego火起来. QML的Loader元素经常备用来动态加载QML组件.可以使用source属性或者so ...

  9. nm applet disable

    http://support.qacafe.com/knowledge-base/how-do-i-prevent-network-manager-from-controlling-an-interf ...

  10. log4j打印出线程号和方法名

    先参考实现配置,如果想要更加详细的配置,可加上更多参数: log4j.rootLogger = INFO,FILE,CONSOLE log4j.appender.FILE.Threshold=INFO ...