MDA之路

MDA,UML,XML,Eclipse及Java相关的Blog
posts - 53, comments - 494, trackbacks - 0, articles - 2
  BlogJava :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理

DLL编写教程

Posted on 2007-09-11 22:13 wxb_nudt 阅读(64439) 评论(113)  编辑  收藏 所属分类: 实用编程技术

 

DLL编写教程

半年不能上网,最近网络终于通了,终于可以更新博客了,写点什么呢?决定最近写一个编程技术系列,其内容是一些通用的编程技术。例如DLLCOMSocket,多线程等等。这些技术的特点就是使用广泛,但是误解很多;网上教程很多,但是几乎没有什么优质良品。我以近几个月来的编程经验发现,很有必要好好的总结一下这些编程技术了。一来对自己是总结提高,二来可以方便光顾我博客的朋友。

好了,废话少说,言归正传。第一篇就是《DLL编写教程》,为什么起这么土的名字呢?为什么不叫《轻轻松松写DLL》或者《DLL一日通》呢?或者更nb的《深入简出DLL》呢?呵呵,常常上网搜索资料的弟兄自然知道。

本文对通用的DLL技术做了一个总结,并提供了源代码打包下载,下载地址为:

http://www.blogjava.net/Files/wxb_nudt/DLL_SRC.rar

DLL的优点

简单的说,dll有以下几个优点:

1)      节省内存。同一个软件模块,若是以源代码的形式重用,则会被编译到不同的可执行程序中,同时运行这些exe时这些模块的二进制码会被重复加载到内存中。如果使用dll,则只在内存中加载一次,所有使用该dll的进程会共享此块内存(当然,像dll中的全局变量这种东西是会被每个进程复制一份的)。

2)      不需编译的软件系统升级,若一个软件系统使用了dll,则该dll被改变(函数名不变)时,系统升级只需要更换此dll即可,不需要重新编译整个系统。事实上,很多软件都是以这种方式升级的。例如我们经常玩的星际、魔兽等游戏也是这样进行版本升级的。

3)      Dll库可以供多种编程语言使用,例如用c编写的dll可以在vb中调用。这一点上DLL还做得很不够,因此在dll的基础上发明了COM技术,更好的解决了一系列问题。

最简单的dll

开始写dll之前,你需要一个c/c++编译器和链接器,并关闭你的IDE。是的,把你的VCC++ BUILDER之类的东东都关掉,并打开你以往只用来记电话的记事本程序。不这样做的话,你可能一辈子也不明白dll的真谛。我使用了VC自带的cl编译器和link链接器,它们一般都在vcbin目录下。(若你没有在安装vc的时候选择注册环境变量,那么就立刻将它们的路径加入path吧)如果你还是因为离开了IDE而害怕到哭泣的话,你可以关闭这个页面并继续去看《VC++技术内幕》之类无聊的书了。

最简单的dll并不比chelloworld难,只要一个DllMain函数即可,包含objbase.h头文件(支持COM技术的一个头文件)。若你觉得这个头文件名字难记,那么用windows.H也可以。源代码如下:dll_nolib.cpp

#include <objbase.h>

#include <iostream.h>

BOOL APIENTRY DllMain(HANDLE hModule, DWORD dwReason, void* lpReserved)

{

    HANDLE g_hModule;

    switch(dwReason)

    {

    case DLL_PROCESS_ATTACH:

       cout<<"Dll is attached!"<<endl;

       g_hModule = (HINSTANCE)hModule;

       break;

    case DLL_PROCESS_DETACH:

       cout<<"Dll is detached!"<<endl;

       g_hModule=NULL;

       break;

    }

    return true;

}

其中DllMain是每个dll的入口函数,如同cmain函数一样。DllMain带有三个参数,hModule表示本dll的实例句柄(听不懂就不理它,写过windows程序的自然懂),dwReason表示dll当前所处的状态,例如DLL_PROCESS_ATTACH表示dll刚刚被加载到一个进程中,DLL_PROCESS_DETACH表示dll刚刚从一个进程中卸载。当然还有表示加载到线程中和从线程中卸载的状态,这里省略。最后一个参数是一个保留参数(目前和dll的一些状态相关,但是很少使用)。

从上面的程序可以看出,当dll被加载到一个进程中时,dll打印"Dll is attached!"语句;当dll从进程中卸载时,打印"Dll is detached!"语句。

编译dll需要以下两条命令:

cl /c dll_nolib.cpp

这条命令会将cpp编译为obj文件,若不使用/c参数则cl还会试图继续将obj链接为exe,但是这里是一个dll,没有main函数,因此会报错。不要紧,继续使用链接命令。

Link /dll dll_nolib.obj

这条命令会生成dll_nolib.dll

注意,因为编译命令比较简单,所以本文不讨论nmake,有兴趣的可以使用nmake,或者写个bat批处理来编译链接dll

加载DLL(显式调用)

使用dll大体上有两种方式,显式调用和隐式调用。这里首先介绍显式调用。编写一个客户端程序:dll_nolib_client.cpp

#include <windows.h>

#include <iostream.h>

int main(void)

{

    //加载我们的dll

    HINSTANCE hinst=::LoadLibrary("dll_nolib.dll"); 

    if (NULL != hinst)

    {

       cout<<"dll loaded!"<<endl;

    }

    return 0;

}

注意,调用dll使用LoadLibrary函数,它的参数就是dll的路径和名称,返回值是dll的句柄。 使用如下命令编译链接客户端:

Cl dll_nolib_client.cpp

并执行dll_nolib_client.exe,得到如下结果:

Dll is attached!

dll loaded!

Dll is detached!

以上结果表明dll已经被客户端加载过。但是这样仅仅能够将dll加载到内存,不能找到dll中的函数。

使用dumpbin命令查看DLL中的函数

Dumpbin命令可以查看一个dll中的输出函数符号名,键入如下命令:

Dumpbin –exports dll_nolib.dll

通过查看,发现dll_nolib.dll并没有输出任何函数。

如何在dll中定义输出函数

总体来说有两种方法,一种是添加一个def定义文件,在此文件中定义dll中要输出的函数;第二种是在源代码中待输出的函数前加上__declspec(dllexport)关键字。

Def文件

首先写一个带有输出函数的dll,源代码如下:dll_def.cpp

#include <objbase.h>

#include <iostream.h>

void FuncInDll (void)

{

    cout<<"FuncInDll is called!"<<endl;

}

BOOL APIENTRY DllMain(HANDLE hModule, DWORD dwReason, void* lpReserved)

{

    HANDLE g_hModule;

    switch(dwReason)

    {

    case DLL_PROCESS_ATTACH:

       g_hModule = (HINSTANCE)hModule;

       break;

    case DLL_PROCESS_DETACH:

        g_hModule=NULL;

        break;

    }

    return TRUE;

}

这个dlldef文件如下:dll_def.def

;

; dll_def module-definition file

;

LIBRARY         dll_def.dll

DESCRIPTION     '(c)2007-2009 Wang Xuebin'

EXPORTS

                FuncInDll @1 PRIVATE

你会发现def的语法很简单,首先是LIBRARY关键字,指定dll的名字;然后一个可选的关键字DESCRIPTION,后面写上版权等信息(不写也可以);最后是EXPORTS关键字,后面写上dll中所有要输出的函数名或变量名,然后接上@以及依次编号的数字(从1N),最后接上修饰符。

用如下命令编译链接带有def文件的dll

Cl /c dll_def.cpp

Link /dll dll_def.obj /def:dll_def.def

再调用dumpbin查看生成的dll_def.dll

Dumpbin –exports dll_def.dll

得到如下结果:

Dump of file dll_def.dll

File Type: DLL

 Section contains the following exports for dll_def.dll

           0 characteristics

    46E4EE98 time date stamp Mon Sep 10 15:13:28 2007

        0.00 version

           1 ordinal base

           1 number of functions

           1 number of names

    ordinal hint RVA      name

          1    0 00001000 FuncInDll

 Summary

        2000 .data

        1000 .rdata

        1000 .reloc

        6000 .text

观察这一行

          1    0 00001000 FuncInDll

会发现该dll输出了函数FuncInDll

显式调用DLL中的函数

写一个dll_def.dll的客户端程序:dll_def_client.cpp

#include <windows.h>

#include <iostream.h>

int main(void)

{

    //定义一个函数指针

    typedef void (* DLLWITHLIB )(void); 

    //定义一个函数指针变量

    DLLWITHLIB pfFuncInDll = NULL; 

    //加载我们的dll

    HINSTANCE hinst=::LoadLibrary("dll_def.dll"); 

    if (NULL != hinst)

    {

       cout<<"dll loaded!"<<endl;

    }

    //找到dllFuncInDll函数

    pfFuncInDll = (DLLWITHLIB)GetProcAddress(hinst, "FuncInDll"); 

    //调用dll里的函数

    if (NULL != pfFuncInDll)

    {

       (*pfFuncInDll)();  

    }

    return 0;

}

有两个地方值得注意,第一是函数指针的定义和使用,不懂的随便找本c++书看看;第二是GetProcAddress的使用,这个API是用来查找dll中的函数地址的,第一个参数是DLL的句柄,即LoadLibrary返回的句柄,第二个参数是dll中的函数名称,即dumpbin中输出的函数名(注意,这里的函数名称指的是编译后的函数名,不一定等于dll源代码中的函数名)。

编译链接这个客户端程序,并执行会得到:

dll loaded!

FuncInDll is called!

这表明客户端成功调用了dll中的函数FuncInDll

__declspec(dllexport)

为每个dlldef显得很繁杂,目前def使用已经比较少了,更多的是使用__declspec(dllexport)在源代码中定义dll的输出函数。

Dll写法同上,去掉def文件,并在每个要输出的函数前面加上声明__declspec(dllexport),例如:

__declspec(dllexport) void FuncInDll (void)

这里提供一个dll源程序dll_withlib.cpp,然后编译链接。链接时不需要指定/DEF:参数,直接加/DLL参数即可,

Cl /c dll_withlib.cpp

Link /dll dll_withlib.obj

然后使用dumpbin命令查看,得到:

1    0 00001000 ?FuncInDll@@YAXXZ

可知编译后的函数名为?FuncInDll@@YAXXZ,而并不是FuncInDll,这是因为c++编译器基于函数重载的考虑,会更改函数名,这样使用显式调用的时候,也必须使用这个更改后的函数名,这显然给客户带来麻烦。为了避免这种现象,可以使用extern “C”指令来命令c++编译器以c编译器的方式来命名该函数。修改后的函数声明为:

extern "C" __declspec(dllexport) void FuncInDll (void)

dumpbin命令结果:

1    0 00001000 FuncInDll

这样,显式调用时只需查找函数名为FuncInDll的函数即可成功。

extern “C”

使用extern “C”关键字实际上相当于一个编译器的开关,它可以将c++语言的函数编译为c语言的函数名称。即保持编译后的函数符号名等于源代码中的函数名称。

隐式调用DLL

显式调用显得非常复杂,每次都要LoadLibrary,并且每个函数都必须使用GetProcAddress来得到函数指针,这对于大量使用dll函数的客户是一种困扰。而隐式调用能够像使用c函数库一样使用dll中的函数,非常方便快捷。

下面是一个隐式调用的例子:dll包含两个文件dll_withlibAndH.cppdll_withlibAndH.h

代码如下:dll_withlibAndH.h

extern "C" __declspec(dllexport) void FuncInDll (void);

dll_withlibAndH.cpp

#include <objbase.h>

#include <iostream.h>

#include "dll_withLibAndH.h"//看到没有,这就是我们增加的头文件

extern "C" __declspec(dllexport) void FuncInDll (void)

{

    cout<<"FuncInDll is called!"<<endl;

}

BOOL APIENTRY DllMain(HANDLE hModule, DWORD dwReason, void* lpReserved)

{

    HANDLE g_hModule;

    switch(dwReason)

    {

    case DLL_PROCESS_ATTACH:

       g_hModule = (HINSTANCE)hModule;

       break;

    case DLL_PROCESS_DETACH:

        g_hModule=NULL;

        break;

    }

    return TRUE;

}

编译链接命令:

Cl /c dll_withlibAndH.cpp

Link /dll dll_withlibAndH.obj

在进行隐式调用的时候需要在客户端引入头文件,并在链接时指明dll对应的lib文件(dll只要有函数输出,则链接的时候会产生一个与dll同名的lib文件)位置和名称。然后如同调用api函数库中的函数一样调用dll中的函数,不需要显式的LoadLibraryGetProcAddress。使用最为方便。客户端代码如下:dll_withlibAndH_client.cpp

#include "dll_withLibAndH.h"

//注意路径,加载 dll的另一种方法是 Project | setting | link 设置里

#pragma comment(lib,"dll_withLibAndH.lib")

int main(void)

{

    FuncInDll();//只要这样我们就可以调用dll里的函数了

    return 0;

}

__declspec(dllexport)__declspec(dllimport)配对使用

上面一种隐式调用的方法很不错,但是在调用DLL中的对象和重载函数时会出现问题。因为使用extern “C”修饰了输出函数,因此重载函数肯定是会出问题的,因为它们都将被编译为同一个输出符号串(c语言是不支持重载的)。

事实上不使用extern “C”是可行的,这时函数会被编译为c++符号串,例如(?FuncInDll@@YAXH@Z ?FuncInDll@@YAXXZ),当客户端也是c++时,也能正确的隐式调用。

这时要考虑一个情况:若DLL1.CPP是源,DLL2.CPP使用了DLL1中的函数,但同时DLL2也是一个DLL,也要输出一些函数供Client.CPP使用。那么在DLL2中如何声明所有的函数,其中包含了从DLL1中引入的函数,还包括自己要输出的函数。这个时候就需要同时使用__declspec(dllexport)__declspec(dllimport)了。前者用来修饰本dll中的输出函数,后者用来修饰从其它dll中引入的函数。

所有的源代码包括DLL1.HDLL1.CPPDLL2.HDLL2.CPPClient.cpp。源代码可以在下载的包中找到。你可以编译链接并运行试试。

值得关注的是DLL1DLL2中都使用的一个编码方法,见DLL2.H

#ifdef DLL_DLL2_EXPORTS

#define DLL_DLL2_API __declspec(dllexport)

#else

#define DLL_DLL2_API __declspec(dllimport)

#endif

DLL_DLL2_API void FuncInDll2(void);

DLL_DLL2_API void FuncInDll2(int);

在头文件中以这种方式定义宏DLL_DLL2_EXPORTSDLL_DLL2_API,可以确保DLL端的函数用__declspec(dllexport)修饰,而客户端的函数用__declspec(dllimport)修饰。当然,记得在编译dll时加上参数/D “DLL_DLL2_EXPORTS”,或者干脆就在dllcpp文件第一行加上#define DLL_DLL2_EXPORTS

VC生成的代码也是这样的!事实证明,我是抄袭它的,hoho

DLL中的全局变量和对象

解决了重载函数的问题,那么dll中的全局变量和对象都不是问题了,只是有一点语法需要注意。如源代码所示:dll_object.h

#ifdef DLL_OBJECT_EXPORTS

#define DLL_OBJECT_API __declspec(dllexport)

#else

#define DLL_OBJECT_API __declspec(dllimport)

#endif

DLL_OBJECT_API void FuncInDll(void);

extern DLL_OBJECT_API int g_nDll;

class DLL_OBJECT_API CDll_Object {

public:

    CDll_Object(void);

    show(void);

    // TODO: add your methods here.

};

Cpp文件dll_object.cpp如下:

#define DLL_OBJECT_EXPORTS

#include <objbase.h>

#include <iostream.h>

#include "dll_object.h"

DLL_OBJECT_API void FuncInDll(void)

{

    cout<<"FuncInDll is called!"<<endl;

}

DLL_OBJECT_API int g_nDll = 9;

CDll_Object::CDll_Object()

{

    cout<<"ctor of CDll_Object"<<endl;

}

CDll_Object::show()

{

    cout<<"function show in class CDll_Object"<<endl;

}

BOOL APIENTRY DllMain(HANDLE hModule, DWORD dwReason, void* lpReserved)

{

    HANDLE g_hModule;

    switch(dwReason)

    {

    case DLL_PROCESS_ATTACH:

       g_hModule = (HINSTANCE)hModule;

       break;

    case DLL_PROCESS_DETACH:

        g_hModule=NULL;

        break;

    }

    return TRUE;

}

编译链接完后Dumpbin一下,可以看到输出了5个符号:

1    0 00001040 ??0CDll_Object@@QAE@XZ

 2    1 00001000 ??4CDll_Object@@QAEAAV0@ABV0@@Z

 3    2 00001020 ?FuncInDll@@YAXXZ

 4    3 00008040 ?g_nDll@@3HA

 5    4 00001069 ?show@CDll_Object@@QAEHXZ

它们分别代表类CDll_Object,类的构造函数,FuncInDll函数,全局变量g_nDll和类的成员函数show。下面是客户端代码:dll_object_client.cpp

#include "dll_object.h"

#include <iostream.h>

//注意路径,加载 dll的另一种方法是 Project | setting | link 设置里

#pragma comment(lib,"dll_object.lib")

int main(void)

{

    cout<<"call dll"<<endl;

    cout<<"call function in dll"<<endl;

    FuncInDll();//只要这样我们就可以调用dll里的函数了

    cout<<"global var in dll g_nDll ="<<g_nDll<<endl;

    cout<<"call member function of class CDll_Object in dll"<<endl;

    CDll_Object obj;

    obj.show();

    return 0;

}

运行这个客户端可以看到:

call dll

call function in dll

FuncInDll is called!

global var in dll g_nDll =9

call member function of class CDll_Object in dll

ctor of CDll_Object

function show in class CDll_Object

可知,在客户端成功的访问了dll中的全局变量,并创建了dll中定义的C++对象,还调用了该对象的成员函数。

中间的小结

牢记一点,说到底,DLL是对应C语言的动态链接技术,在输出C函数和变量时显得方便快捷;而在输出C++类、函数时需要通过各种手段,而且也并没有完美的解决方案,除非客户端也是c++

记住,只有COM是对应C++语言的技术。

下面开始对各各问题一一小结。

显式调用和隐式调用

何时使用显式调用?何时使用隐式调用?我认为,只有一个时候使用显式调用是合理的,就是当客户端不是C/C++的时候。这时是无法隐式调用的。例如用VB调用C++写的dll。(VB我不会,所以没有例子)

Def__declspec(dllexport)

其实def的功能相当于extern “C” __declspec(dllexport),所以它也仅能处理C函数,而不能处理重载函数。而__declspec(dllexport)__declspec(dllimport)配合使用能够适应任何情况,因此__declspec(dllexport)是更为先进的方法。所以,目前普遍的看法是不使用def文件,我也同意这个看法。

从其它语言调用DLL

从其它编程语言中调用DLL,有两个最大的问题,第一个就是函数符号的问题,前面已经多次提过了。这里有个两难选择,若使用extern “C”,则函数名称保持不变,调用较方便,但是不支持函数重载等一系列c++功能;若不使用extern “C”,则调用前要查看编译后的符号,非常不方便。

第二个问题就是函数调用压栈顺序的问题,即__cdecl__stdcall的问题。__cdecl是常规的C/C++调用约定,这种调用约定下,函数调用后栈的清理工作是由调用者完成的。__stdcall是标准的调用约定,即这些函数将在返回到调用者之前将参数从栈中删除。

这两个问题DLL都不能很好的解决,只能说凑合着用。但是在COM中,都得到了完美的解决。所以,要在Windows平台实现语言无关性,还是只有使用COM中间件。

总而言之,除非客户端也使用C++,否则dll是不便于支持函数重载、类等c++特性的。DLLc函数的支持很好,我想这也是为什么windows的函数库使用Cdll实现的理由之一。

VC中编写DLL

VC中创建、编译、链接dll是非常方便的,点击fileàNewàProjectàWin32 Dynamic-Link Library,输入dll名称dll_InVC然后点击确定。然后选择A DLL that export some symbols,点击Finish。即可得到一个完整的DLL

仔细观察其源代码,是不是有很多地方似曾相识啊,哈哈!

最后

贴上女儿近照一张,小家伙长得太快了!

评论共2页: 1 2 下一页 

评论

# re: DLL编写教程[未登录]  回复  更多评论   

2007-12-10 14:09 by zz
很好.拜一下
已转到我博客,已注明作者与原文链接

# re: DLL编写教程  回复  更多评论   

2007-12-11 12:58 by wxb_nudt
@zz
好的,谢谢!

# re: DLL编写教程  回复  更多评论   

2007-12-11 21:54 by 苏三
恩 ,写的很好。期待。

# re: DLL编写教程  回复  更多评论   

2007-12-14 12:30 by dAYu
非常好,谢谢!

# re: DLL编写教程  回复  更多评论   

2007-12-19 01:02 by xx
很有启发,拜读了,谢谢

# re: DLL编写教程  回复  更多评论   

2007-12-21 11:40 by jjlsky
非常感谢
让我对dll的编制过程有所理解
有待实践
呵呵

# re: DLL编写教程  回复  更多评论   

2007-12-27 10:53 by 1211
我靠,写的太好了,比一些垃圾书上面写得好多了

# re: DLL编写教程  回复  更多评论   

2008-01-11 17:04 by hitma
走来又飘走。

# re: DLL编写教程  回复  更多评论   

2008-01-31 02:56 by samwon
四个字:豁然开朗!

# re: DLL编写教程  回复  更多评论   

2008-02-13 19:04 by
内容很好 但是.....能否换个歌 第一次打开我还以为电脑又中毒了 吓死我了

# re: DLL编写教程  回复  更多评论   

2008-02-23 14:20 by wenjiahe
从Google搜到你这片文章,写的太好了。
加入收藏夹了,希望尽快看到你关于com技术的高论。

# re: DLL编写教程  回复  更多评论   

2008-03-10 20:43 by jef
楼主在国防科大上学和工作的,博士学历

# re: DLL编写教程[未登录]  回复  更多评论   

2008-03-13 11:16 by wangcheng
虽然有这么多人说写得好,但我还是得说:"真得写的非常好!!"

# re: DLL编写教程  回复  更多评论   

2008-03-19 10:30 by deadjn
玩得够透了,佩服!

# re: DLL编写教程  回复  更多评论   

2008-03-20 14:39 by kris
写得太好了,我查了很多资料,这篇文章写得既有条理,有清晰,果然是大作啊

# re: DLL编写教程  回复  更多评论   

2008-04-02 08:28 by Ulti
呵呵,文美,照片也美

# re: DLL编写教程  回复  更多评论   

2008-04-08 13:11 by 王俊华
写的非常好!谢谢!

# re: DLL编写教程  回复  更多评论   

2008-04-08 16:30 by 白狐
Thanks !

# re: DLL编写教程  回复  更多评论   

2008-04-13 22:27 by ziffwong
清晰明了,非常不错。3x!

# re: DLL编写教程  回复  更多评论   

2008-04-14 00:16 by 陈帅
十分感谢。。。

# re: DLL编写教程  回复  更多评论   

2008-04-17 15:14 by Alexander
博主写得好!最后的方法是不是把所有DLL中的全局符号都输出了?

# 求教  回复  更多评论   

2008-04-20 15:37 by 逍遥郁闷
现在在网上查资料的时候很郁闷,最近想写一个能传入和传入字符串的DLL,可是我发现网上那个有关DLL编程的帖子全用int来举例,有没有那位大哥来一个string,CString,String之类的,哪怕你传入和传出数组也行。。。。。郁闷。
这位大哥你能不能在抽点时间写一个能在电脑上注册的DLL,用你说的这些方法写的DLL都无法注册,不能注册使用的时候非常不方便。

# re: DLL编写教程  回复  更多评论   

2008-05-04 18:02 by wycoo
谢谢啊

# re: DLL编写教程  回复  更多评论   

2008-05-28 21:54 by pzy123cn
现在在网上查资料的时候很郁闷,最近想写一个能传入和传入字符串的DLL,可是我发现网上那个有关DLL编程的帖子全用int来举例,有没有那位大哥来一个string,CString,String之类的,哪怕你传入和传出数组也行。。。。。郁闷。
这位大哥你能不能在抽点时间写一个能在电脑上注册的DLL,用你说的这些方法写的DLL都无法注册,不能注册使用的时候非常不方便。


我前几天也遇到了这个问题 , 我的解决方法是用指针

在.h文件中定义

extern "C" void __declspec(dllexport) SetTestS(char * s);
extern "C" __declspec(dllexport) char * GetTestS();

在cpp中:

char * tests= 0; // 全局变量
char * GetTestS()
{
//获得tests的值
return tests ;
}
void SetTestS(char * s)
{
//设置tests
tests = s ;
}

# re: DLL编写教程  回复  更多评论   

2008-06-18 17:45 by zache
不是所有的DLL都能注册的,能注册是DLL要实现DllRegisterServer函数
RegSvr32只是调用该函数而已。你说的恐怕是COM了,那又是个大课题

# re: DLL编写教程[未登录]  回复  更多评论   

2008-07-16 17:34 by oo
谢谢楼主啊

# re: DLL编写教程[未登录]  回复  更多评论   

2008-07-21 11:45 by oo
受益匪浅啊!

# re: DLL编写教程  回复  更多评论   

2008-07-25 13:54 by daodao
不是很懂,但感覺寫的不錯!
謝謝樓主!你的女兒看起來很聰明.

# re: DLL编写教程  回复  更多评论   

2008-07-29 14:54 by mangshe0
好!写的太好了!谢谢楼主,我看了一下午,学到了很多东西。真的感谢您.

# re: DLL编写教程  回复  更多评论   

2008-07-29 15:56 by jiejie
十分感激

# re: DLL编写教程  回复  更多评论   

2008-08-22 10:40 by YMM
真是好文啊。这个才是偶需要的,好文!

# re: DLL编写教程  回复  更多评论   

2008-09-02 16:45 by huhusu
很好的文章 谢谢!

# re: DLL编写教程  回复  更多评论   

2008-09-12 15:37 by piit
再怎么感谢你也无法表达我对你的感激之情啊,祝你全家幸福!

# re: DLL编写教程  回复  更多评论   

2008-09-20 22:33 by 小松
写的漂亮,小姑娘更漂亮

# re: DLL编写教程[未登录]  回复  更多评论   

2008-11-17 11:07 by joe
很好的文章 谢谢!

# re: DLL编写教程  回复  更多评论   

2008-12-15 13:20 by 编程爱好者
感谢楼主的无私奉献!

# re: DLL编写教程  回复  更多评论   

2008-12-25 10:52 by lianyi
尽管该说的别人都说了,可是我还是忍不住要说一句:写得实在太好了!我太佩服你了!我将你的博客珍藏了,以后努力向你学习!

# re: DLL编写教程  回复  更多评论   

2008-12-30 22:18 by lyl0719
真的不错,谢谢你。

# re: DLL编写教程[未登录]  回复  更多评论   

2009-01-06 12:26 by h
怎一个强字了得………………

# re: DLL编写教程  回复  更多评论   

2009-02-09 20:29 by 胡致璘
写得太好了。
我曾花了近一个星期的时间去找有关DLL编程的资料。找到了一堆资料,乱七八糟的,今看了你的文章之后我对DLL编程豁然开朗

# re: DLL编写教程  回复  更多评论   

2009-02-16 20:12 by 123
这里好像是武汉的中山公园呀
1

# re: DLL编写教程[未登录]  回复  更多评论   

2009-02-17 22:02 by wxb_nudt
@123
错了,是北京动物园啊!

# re: DLL编写教程  回复  更多评论   

2009-02-26 10:28 by kook@21cn.com
楼上的文章写的太好了,该赞的大家都已赞完。
我给你发了封EMAIL,没等到你的回复,大概意思在这里说一下,有一个DLL,没有原文件,只有.h和.lib文件,实现功能有:socket通信,最重要是实现了一个通用的打包解包功能,其他功能还有指定线程数,短联接长联接,滑动窗口控制,UDP,回调函数等,其性能非常卓越,公司每日几千万的吞吐量。我学着重写了一遍,源码没勇气拿出手,只有楼主这水平的重写一遍才行,在博客上发出来供大家学习,保证是一篇非常好的博文。
头文件怎么给你?
欢迎有楼主这水平的人参与,kook@21cn.com 联系。

说不写我家小子可以和楼主千金订个娃娃亲,haha。照片如下:
http://photo.163.com/photo/youless1/#m=1&ai=27240730&p=1&n=60&cp=1

# re: DLL编写教程  回复  更多评论   

2009-04-22 16:37 by 11
非常感谢,比一些破书上的好多了!

# re: DLL编写教程  回复  更多评论   

2009-04-22 16:37 by 11
非常感谢,比一些破书上的好多了!

# re: DLL编写教程  回复  更多评论   

2009-06-14 15:44 by 零魂
写的太好了,虽然看到该赞的大家都已经赞完了,不过我还是忍不住要顶一下。
我心中的很多疑惑基本在你这一篇文章里面全给解答了....

# re: DLL编写教程  回复  更多评论   

2009-06-27 20:14 by WwcMonkey
呵呵,很朴实、实用的入门文章
总算开了个头, 谢了!

期待更多大作

# re: DLL编写教程  回复  更多评论   

2009-07-23 00:11 by Master Wei
好不容易找到这篇文章的原始地址
特赶来道谢
教程写得太好了

# 怎么编译?  回复  更多评论   

2009-09-02 21:55 by dll
怎么弄?是在命令行里面写命令,还是什么?

# re: DLL编写教程  回复  更多评论   

2010-02-21 14:48 by 慢步者
支持好文!

# re: DLL编写教程[未登录]  回复  更多评论   

2010-02-23 22:20 by 萧何
我感动的泪流满面,谢谢博主

# re: DLL编写教程  回复  更多评论   

2010-02-26 13:33 by 水辰
特来登门道谢!文章不是一般的好

# re: DLL编写教程[未登录]  回复  更多评论   

2010-02-26 14:08 by wxb_nudt
@萧何
内牛满面夸张了点吧,哈哈,大家新年好。

# re: DLL编写教程  回复  更多评论   

2010-03-18 16:42 by lizhi
写了那么多年的程序,还搞不大清楚,真的汗颜,楼主写的明了清晰

# re: DLL编写教程  回复  更多评论   

2010-04-20 10:39 by epinszteinic
两个字:NB!!!!
写得真是太好了!!!!
感激之情犹如滔滔江水!!!!
赶紧存下来!!!!

# re: DLL编写教程  回复  更多评论   

2010-07-26 14:16 by zz_yun
博主事业有成,生活幸福啊!

# re: DLL编写教程  回复  更多评论   

2010-08-26 15:56 by shirui
太感谢楼主了,写得太好了,可为什么我下载源代码的时候没速度呢,呜呜~~~~(>_<)~~~~ ,能不能把源代码发到我邮箱一份,我的邮箱地址是shiruiyiruo@msn.cn
非常感谢

# re: DLL编写教程  回复  更多评论   

2010-09-20 14:48 by 柯南
感谢楼主的教程

# re: DLL编写教程  回复  更多评论   

2010-12-04 00:42 by 感谢祖国
看完楼主的教程。。解开了我以前很多的疑惑。。楼主可否推荐几本书,多想。

# re: DLL编写教程  回复  更多评论   

2011-01-01 13:28 by kingbird
好,比那些以上来就教我用IDE写DLL的强多了,他们以为会用就好,可是我怎么也不能理解,我觉得编程人员向成为高手,就要从最朴实开始。。。。远离IDE,成就高手。

# re: DLL编写教程[未登录]  回复  更多评论   

2011-01-04 16:37 by
祝楼主新年快乐,呵呵,小女越来越漂亮

# re: DLL编写教程  回复  更多评论   

2011-01-06 10:33 by turtle_2
大牛啊,讲的很清楚,谢谢。

# re: DLL编写教程  回复  更多评论   

2011-01-17 08:21 by micRabbit
写的很霸气

# re: DLL编写教程  回复  更多评论   

2011-02-26 21:12 by 过路蚂蚁
写的真好,兼备才气和逻辑,难得

# re: DLL编写教程  回复  更多评论   

2011-03-01 14:52 by Cathy
谢谢博主,这篇文章对我帮助很大,所以很想把它分享给更多人。
转发后博客中已注明作者和出处。

# re: DLL编写教程  回复  更多评论   

2011-04-02 18:02 by 王朋
赞一个

# re: DLL编写教程[未登录]  回复  更多评论   

2011-04-03 20:08 by RYAN
感谢博主!

# re: DLL编写教程  回复  更多评论   

2011-05-20 12:56 by jj

# re: DLL编写教程  回复  更多评论   

2011-05-20 12:57 by jj
顶weqw

# re: DLL编写教程  回复  更多评论   

2011-05-30 12:09 by 踏血无痕
令人敬佩的文章,谢谢了

# re: DLL编写教程  回复  更多评论   

2011-06-03 01:00 by 陈水文
qq 1300510038 很想跟你学习

# re: DLL编写教程  回复  更多评论   

2011-06-21 11:19 by 杨元
我是想在VB中调用Dll,必须要用C写才可以,看了您的文章,很好!
而且感觉C语言比VB方便很多

# re: DLL编写教程  回复  更多评论   

2011-07-20 11:00 by 无语紫玉
看完了~~获益匪浅啊~~

# re: DLL编写教程  回复  更多评论   

2011-09-07 19:09 by fan
小小的入门了

# re: DLL编写教程  回复  更多评论   

2012-02-23 22:55 by DllMain
写的很详细,支持一下

# re: DLL编写教程  回复  更多评论   

2012-02-24 14:16 by 团团
感谢楼主,写的很详细!
总算是入门了,呵呵

# 写的很好  回复  更多评论   

2012-02-26 19:08 by DLL大全
写的很好,支持一下

# re: DLL编写教程  回复  更多评论   

2012-03-03 22:21 by Alex.Wu
非常好的教程,起码我是在这里搞懂如何编写dll的。十分感谢

# re: DLL编写教程  回复  更多评论   

2012-03-04 11:49 by c初级程序员
谢谢楼主,让我知识面有广了

# re: DLL编写教程[未登录]  回复  更多评论   

2012-07-10 22:30 by 飞鸟
很不错,一个偶然的机会让我学会了DLL,哈哈

# re: DLL编写教程  回复  更多评论   

2012-08-14 15:36 by Logger
获益良多,可惜没有介绍类的导出方法。期待楼主继续完善。

# re: DLL编写教程[未登录]  回复  更多评论   

2012-10-02 22:01 by lobby
找了好久,终于找到说的清晰明了的好文章,太好了;学到了很多,谢谢楼主。

# re: DLL编写教程[未登录]  回复  更多评论   

2012-12-04 12:26 by 123
教程很清晰,收获很大,非常感谢!!

# re: DLL编写教程[未登录]  回复  更多评论   

2013-03-20 16:47 by Andy
程序媛辛苦了

# re: DLL编写教程  回复  更多评论   

2013-03-27 20:59 by 麦穗儿
写得真是太好了!

# re: DLL编写教程  回复  更多评论   

2013-04-13 16:03 by 王海辉
不得不好,真的是很好。

# re: DLL编写教程[未登录]  回复  更多评论   

2013-07-23 23:47 by 小辉
非常棒!!!很清楚~

# re: DLL编写教程  回复  更多评论   

2013-08-15 17:59 by feitian
刚拜读完文章,写得很不错,受益匪浅,期待更多更好的文章!

# re: DLL编写教程  回复  更多评论   

2013-08-16 13:09 by 沈军涛
不错,学习了

# re: DLL编写教程  回复  更多评论   

2013-09-06 01:46 by Frankie
实在太感谢了,比书里讲的好多了

# re: DLL编写教程  回复  更多评论   

2013-09-14 14:12 by be.truth
__declspec(dllexport) 导出不了函数,用dumpbin看不到导出函数 用的是vs2008 的CL

# re: DLL编写教程  回复  更多评论   

2013-10-03 16:47 by caotengfei
厉害,学习了

# re: DLL编写教程  回复  更多评论   

2013-10-20 16:43 by thinkercui
我忍不住,要感谢楼主,为传播程序员文化所做出的努力!
谢谢。

# re: DLL编写教程[未登录]  回复  更多评论   

2014-02-11 23:12 by
虽然这么多赞的,但是我还要来赞一下!!

# re: DLL编写教程[未登录]  回复  更多评论   

2014-03-13 21:56 by 无名
写的十分清晰,十分感谢

# re: DLL编写教程[未登录]  回复  更多评论   

2014-04-10 16:53 by 1234
膜拜楼主,非常清晰

# re: DLL编写教程  回复  更多评论   

2014-04-16 03:00 by prx
请教您了:照您的做法,我dll中的h是这样:
#define BASE_EXPORTS
#ifdef BASE_EXPORTS
#define  BASE_API __declspec(dllexport)
#else
#define  BASE_API __declspec(dllimport)
#endif
BASE_API BOOL BASIT;
cpp如下:
BASE_API BOOL BASIT=FALSE;
编译出现:
D:\VC6\MyProjects\Base\Base.cpp(327) : error C2086: 'BASIT' : redefinition
请你指点下!

# re: DLL编写教程  回复  更多评论   

2014-08-21 16:52 by liuruoze
谢谢 很不错的文章

# re: DLL编写教程[未登录]  回复  更多评论   

2015-11-11 22:56 by HelloWorld
楼主好文。我做学习笔记转走了。么么哒

# re: DLL编写教程  回复  更多评论   

2016-08-10 20:56 by liqiao
这不就是一天学会,深入浅出……
:p
评论共2页: 1 2 下一页 

只有注册用户登录后才能发表评论。


网站导航: