blogjava-凯发k8网页登录http://www.blogjava.net/wxb_nudt/mda,uml,xml,eclipse及java相关的blogzh-cnsat, 08 apr 2023 20:43:14 gmtsat, 08 apr 2023 20:43:14 gmt60妈妈生日快乐!http://www.blogjava.net/wxb_nudt/archive/2010/05/20/321496.htmlwxb_nudtwxb_nudtthu, 20 may 2010 12:03:00 gmthttp://www.blogjava.net/wxb_nudt/archive/2010/05/20/321496.htmlhttp://www.blogjava.net/wxb_nudt/comments/321496.htmlhttp://www.blogjava.net/wxb_nudt/archive/2010/05/20/321496.html#feedback0http://www.blogjava.net/wxb_nudt/comments/commentrss/321496.htmlhttp://www.blogjava.net/wxb_nudt/services/trackbacks/321496.html

wxb_nudt 2010-05-20 20:03
]]>
tuxedo安装,license,例子和远程客户端配置http://www.blogjava.net/wxb_nudt/archive/2009/03/14/259772.htmlwxb_nudtwxb_nudtsat, 14 mar 2009 15:25:00 gmthttp://www.blogjava.net/wxb_nudt/archive/2009/03/14/259772.htmlhttp://www.blogjava.net/wxb_nudt/comments/259772.htmlhttp://www.blogjava.net/wxb_nudt/archive/2009/03/14/259772.html#feedback0http://www.blogjava.net/wxb_nudt/comments/commentrss/259772.htmlhttp://www.blogjava.net/wxb_nudt/services/trackbacks/259772.html
tuxedo是一个很好的交易中间件,包含消息中间件等功能,历史悠久,功能强大,是由bea开发的,不过现在属于oracle了。网上的tuxedo入门教程千千万万,几乎没有一个可用的。尤其是在licsence和远程客户端配置这两个问题上,都没有交代清楚。很符合中国的it教程特色:“懂得人看得懂,但是并没有更懂;不懂的人更加不懂了!”。

  

wxb_nudt 2009-03-14 23:25
]]>
博客搬家了!关注的朋友可以去新博客看看!http://www.blogjava.net/wxb_nudt/archive/2008/09/20/230161.htmlwxb_nudtwxb_nudtsat, 20 sep 2008 09:25:00 gmthttp://www.blogjava.net/wxb_nudt/archive/2008/09/20/230161.htmlhttp://www.blogjava.net/wxb_nudt/comments/230161.htmlhttp://www.blogjava.net/wxb_nudt/archive/2008/09/20/230161.html#feedback0http://www.blogjava.net/wxb_nudt/comments/commentrss/230161.htmlhttp://www.blogjava.net/wxb_nudt/services/trackbacks/230161.htmlhttp://blog.csdn.net/wxb_nudt
新博客的第一篇博文是: 
以后两个博客同时更新吧,主要精力在csdn的博客,因为最近java用得很少,在这里似乎不合题。


wxb_nudt 2008-09-20 17:25
]]>
c 中的xml配置文件编程经验http://www.blogjava.net/wxb_nudt/archive/2008/05/27/203317.htmlwxb_nudtwxb_nudttue, 27 may 2008 11:40:00 gmthttp://www.blogjava.net/wxb_nudt/archive/2008/05/27/203317.htmlhttp://www.blogjava.net/wxb_nudt/comments/203317.htmlhttp://www.blogjava.net/wxb_nudt/archive/2008/05/27/203317.html#feedback8http://www.blogjava.net/wxb_nudt/comments/commentrss/203317.htmlhttp://www.blogjava.net/wxb_nudt/services/trackbacks/203317.html阅读全文

wxb_nudt 2008-05-27 19:40
]]>
m文件转换为c/c 文件的编译、绘图、参数、打包问题总结http://www.blogjava.net/wxb_nudt/archive/2008/01/28/178246.htmlwxb_nudtwxb_nudtmon, 28 jan 2008 12:16:00 gmthttp://www.blogjava.net/wxb_nudt/archive/2008/01/28/178246.htmlhttp://www.blogjava.net/wxb_nudt/comments/178246.htmlhttp://www.blogjava.net/wxb_nudt/archive/2008/01/28/178246.html#feedback11http://www.blogjava.net/wxb_nudt/comments/commentrss/178246.htmlhttp://www.blogjava.net/wxb_nudt/services/trackbacks/178246.html
l 如何从m文件生成vc可用的c/c 代码;

l 如何设置编译参数,在vc中编译这些代码;

l 如何在c/c 语言中设置输入输出参数,使之与m代码生成的c 代码一同运行;

l 如何制作包含matlab运行时库的安装程序。

  

wxb_nudt 2008-01-28 20:16
]]>
c 的xml编程经验――libxml2库使用指南http://www.blogjava.net/wxb_nudt/archive/2007/11/18/161340.htmlwxb_nudtwxb_nudtsun, 18 nov 2007 01:42:00 gmthttp://www.blogjava.net/wxb_nudt/archive/2007/11/18/161340.htmlhttp://www.blogjava.net/wxb_nudt/comments/161340.htmlhttp://www.blogjava.net/wxb_nudt/archive/2007/11/18/161340.html#feedback49http://www.blogjava.net/wxb_nudt/comments/commentrss/161340.htmlhttp://www.blogjava.net/wxb_nudt/services/trackbacks/161340.html阅读全文

wxb_nudt 2007-11-18 09:42
]]>
socket编程指南及示例程序http://www.blogjava.net/wxb_nudt/archive/2007/11/01/157623.htmlwxb_nudtwxb_nudtthu, 01 nov 2007 15:20:00 gmthttp://www.blogjava.net/wxb_nudt/archive/2007/11/01/157623.htmlhttp://www.blogjava.net/wxb_nudt/comments/157623.htmlhttp://www.blogjava.net/wxb_nudt/archive/2007/11/01/157623.html#feedback44http://www.blogjava.net/wxb_nudt/comments/commentrss/157623.htmlhttp://www.blogjava.net/wxb_nudt/services/trackbacks/157623.html例子代码就在我的博客中,包括六个udp和tcp发送接受的cpp文件,一个基于mfc的局域网聊天小工具工程,和此小工具的所有运行时库、资源和执行程序。  

wxb_nudt 2007-11-01 23:20
]]>
纸黄金均价管理小软件—黄金秘书http://www.blogjava.net/wxb_nudt/archive/2007/10/20/154584.htmlwxb_nudtwxb_nudtsat, 20 oct 2007 15:13:00 gmthttp://www.blogjava.net/wxb_nudt/archive/2007/10/20/154584.htmlhttp://www.blogjava.net/wxb_nudt/comments/154584.htmlhttp://www.blogjava.net/wxb_nudt/archive/2007/10/20/154584.html#feedback11http://www.blogjava.net/wxb_nudt/comments/commentrss/154584.htmlhttp://www.blogjava.net/wxb_nudt/services/trackbacks/154584.html想试用这个小软件的,可以直接在我的博客下载这两个压缩包,解压后安装即可,安装和试用说明见下节:
  

wxb_nudt 2007-10-20 23:13
]]>
dll编写教程http://www.blogjava.net/wxb_nudt/archive/2007/09/11/144371.htmlwxb_nudtwxb_nudttue, 11 sep 2007 14:13:00 gmthttp://www.blogjava.net/wxb_nudt/archive/2007/09/11/144371.htmlhttp://www.blogjava.net/wxb_nudt/comments/144371.htmlhttp://www.blogjava.net/wxb_nudt/archive/2007/09/11/144371.html#feedback113http://www.blogjava.net/wxb_nudt/comments/commentrss/144371.htmlhttp://www.blogjava.net/wxb_nudt/services/trackbacks/144371.html 

dll编写教程

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

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

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

blogjava-凯发k8网页登录

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

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

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

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

开始写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

#include

bool apientry dllmain(handle hmodule, dword dwreason, void* lpreserved)

{

    handle g_hmodule;

    switch(dwreason)

    {

    case dll_process_attach:

       cout<<"dll is attached!"<

       g_hmodule = (hinstance)hmodule;

       break;

    case dll_process_detach:

       cout<<"dll is detached!"<

       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_nolib_client.cpp

#include

#include

int main(void)

{

    //加载我们的dll

    hinstance hinst=::loadlibrary("dll_nolib.dll"); 

    if (null != hinst)

    {

       cout<<"dll loaded!"<

    }

    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 –exports dll_nolib.dll

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

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

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

#include

#include

void funcindll (void)

{

    cout<<"funcindll is called!"<

}

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,后面写上凯发k8网页登录的版权等信息(不写也可以);最后是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_def.dll的客户端程序:dll_def_client.cpp

#include

#include

int main(void)

{

    //定义一个函数指针

    typedef void (* dllwithlib )(void); 

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

    dllwithlib pffuncindll = null; 

    //加载我们的dll

    hinstance hinst=::loadlibrary("dll_def.dll"); 

    if (null != hinst)

    {

       cout<<"dll loaded!"<

    }

    //找到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

为每个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”关键字实际上相当于一个编译器的开关,它可以将c 语言的函数编译为c语言的函数名称。即保持编译后的函数符号名等于源代码中的函数名称。

显式调用显得非常复杂,每次都要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

#include

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

extern "c" __declspec(dllexport) void funcindll (void)

{

    cout<<"funcindll is called!"<

}

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;

}

上面一种隐式调用的方法很不错,但是在调用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_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

#include

#include "dll_object.h"

dll_object_api void funcindll(void)

{

    cout<<"funcindll is called!"<

}

dll_object_api int g_ndll = 9;

cdll_object::cdll_object()

{

    cout<<"ctor of cdll_object"<

}

cdll_object::show()

{

    cout<<"function show in class cdll_object"<

}

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

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

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

int main(void)

{

    cout<<"call dll"<

    cout<<"call function in dll"<

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

    cout<<"global var in dll g_ndll ="<

    cout<<"call member function of class cdll_object in dll"<

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

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

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

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

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

vc中创建、编译、链接dll是非常方便的,点击fileànewàprojectàwin32 dynamic-link library,输入dll名称dll_invc然后点击确定。然后选择a dll that export some symbols,点击finish。即可得到一个完整的dll

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

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



wxb_nudt 2007-09-11 22:13
]]>
最近不能上网http://www.blogjava.net/wxb_nudt/archive/2007/06/27/126590.htmlwxb_nudtwxb_nudtwed, 27 jun 2007 06:56:00 gmthttp://www.blogjava.net/wxb_nudt/archive/2007/06/27/126590.htmlhttp://www.blogjava.net/wxb_nudt/comments/126590.htmlhttp://www.blogjava.net/wxb_nudt/archive/2007/06/27/126590.html#feedback2http://www.blogjava.net/wxb_nudt/comments/commentrss/126590.htmlhttp://www.blogjava.net/wxb_nudt/services/trackbacks/126590.html大概需要半年才能重新上网了。

wxb_nudt 2007-06-27 14:56
]]>
网站地图