??xml version="1.0" encoding="utf-8" standalone="yes"?>BlogJava-MDA之\http://www.qpkxbc.shop/wxb_nudt/MDA,UML,XML,Eclipse及Java相关的Blogzh-cnSat, 24 Aug 2019 01:03:18 GMTSat, 24 Aug 2019 01:03:18 GMT60妈妈生日快乐Q?/title><link>http://www.qpkxbc.shop/wxb_nudt/archive/2010/05/20/321496.html</link><dc:creator>wxb_nudt</dc:creator><author>wxb_nudt</author><pubDate>Thu, 20 May 2010 12:03:00 GMT</pubDate><guid>http://www.qpkxbc.shop/wxb_nudt/archive/2010/05/20/321496.html</guid><wfw:comment>http://www.qpkxbc.shop/wxb_nudt/comments/321496.html</wfw:comment><comments>http://www.qpkxbc.shop/wxb_nudt/archive/2010/05/20/321496.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.qpkxbc.shop/wxb_nudt/comments/commentRss/321496.html</wfw:commentRss><trackback:ping>http://www.qpkxbc.shop/wxb_nudt/services/trackbacks/321496.html</trackback:ping><description><![CDATA[农历四月初七Q是我妈妈的生日Q祝妈妈生日快乐Q? <img src ="http://www.qpkxbc.shop/wxb_nudt/aggbug/321496.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.qpkxbc.shop/wxb_nudt/" target="_blank">wxb_nudt</a> 2010-05-20 20:03 <a href="http://www.qpkxbc.shop/wxb_nudt/archive/2010/05/20/321496.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Tuxedo安装,license,例子和远E客L配置http://www.qpkxbc.shop/wxb_nudt/archive/2009/03/14/259772.htmlwxb_nudtwxb_nudtSat, 14 Mar 2009 15:25:00 GMThttp://www.qpkxbc.shop/wxb_nudt/archive/2009/03/14/259772.htmlhttp://www.qpkxbc.shop/wxb_nudt/comments/259772.htmlhttp://www.qpkxbc.shop/wxb_nudt/archive/2009/03/14/259772.html#Feedback0http://www.qpkxbc.shop/wxb_nudt/comments/commentRss/259772.htmlhttp://www.qpkxbc.shop/wxb_nudt/services/trackbacks/259772.html
Tuxedo是一个很好的交易中间Ӟ包含消息中间件等功能Q历史悠久,功能强大Q是由BEA开发的Q不q现在属于Oracle了。网上的Tuxedo入门教程千千万万Q几乎没有一个可用的。尤其是在licsence和远E客L配置q两个问题上Q都没有交代清楚。很W合中国的IT教程特色Q“懂得h看得懂,但是q没有更懂;不懂的h更加不懂了!”?

  阅读全文

wxb_nudt 2009-03-14 23:25 发表评论
]]>
博客搬家了!x的朋友可以去新博客看看!http://www.qpkxbc.shop/wxb_nudt/archive/2008/09/20/230161.htmlwxb_nudtwxb_nudtSat, 20 Sep 2008 09:25:00 GMThttp://www.qpkxbc.shop/wxb_nudt/archive/2008/09/20/230161.htmlhttp://www.qpkxbc.shop/wxb_nudt/comments/230161.htmlhttp://www.qpkxbc.shop/wxb_nudt/archive/2008/09/20/230161.html#Feedback0http://www.qpkxbc.shop/wxb_nudt/comments/commentRss/230161.htmlhttp://www.qpkxbc.shop/wxb_nudt/services/trackbacks/230161.htmlhttp://blog.csdn.net/wxb_nudt
新博客的W一博文是Q?nbsp;C++中的数据cd转换Ҏȝ
以后两个博客同时更新吧,主要_֊在csdn的博客,因ؓ最qjava用得很少Q在q里g不合题?br />

wxb_nudt 2008-09-20 17:25 发表评论
]]>
C++中的XML配置文g~程l验http://www.qpkxbc.shop/wxb_nudt/archive/2008/05/27/203317.htmlwxb_nudtwxb_nudtTue, 27 May 2008 11:40:00 GMThttp://www.qpkxbc.shop/wxb_nudt/archive/2008/05/27/203317.htmlhttp://www.qpkxbc.shop/wxb_nudt/comments/203317.htmlhttp://www.qpkxbc.shop/wxb_nudt/archive/2008/05/27/203317.html#Feedback8http://www.qpkxbc.shop/wxb_nudt/comments/commentRss/203317.htmlhttp://www.qpkxbc.shop/wxb_nudt/services/trackbacks/203317.html阅读全文

wxb_nudt 2008-05-27 19:40 发表评论
]]>
m文g转换为C/C++文g的编译、绘图、参数、打包问题ȝhttp://www.qpkxbc.shop/wxb_nudt/archive/2008/01/28/178246.htmlwxb_nudtwxb_nudtMon, 28 Jan 2008 12:16:00 GMThttp://www.qpkxbc.shop/wxb_nudt/archive/2008/01/28/178246.htmlhttp://www.qpkxbc.shop/wxb_nudt/comments/178246.htmlhttp://www.qpkxbc.shop/wxb_nudt/archive/2008/01/28/178246.html#Feedback11http://www.qpkxbc.shop/wxb_nudt/comments/commentRss/178246.htmlhttp://www.qpkxbc.shop/wxb_nudt/services/trackbacks/178246.html
l 如何从m文g生成VC可用的C/C++代码Q?

l 如何讄~译参数Q在VC中编译这些代码;

l 如何在C/C++语言中设|输入输出参敎ͼ使之与M代码生成的C++代码一同运行;

l 如何制作包含matlabq行时库的安装程序?

  阅读全文

wxb_nudt 2008-01-28 20:16 发表评论
]]>
C++的XML~程l验――LIBXML2库用指?/title><link>http://www.qpkxbc.shop/wxb_nudt/archive/2007/11/18/161340.html</link><dc:creator>wxb_nudt</dc:creator><author>wxb_nudt</author><pubDate>Sun, 18 Nov 2007 01:42:00 GMT</pubDate><guid>http://www.qpkxbc.shop/wxb_nudt/archive/2007/11/18/161340.html</guid><wfw:comment>http://www.qpkxbc.shop/wxb_nudt/comments/161340.html</wfw:comment><comments>http://www.qpkxbc.shop/wxb_nudt/archive/2007/11/18/161340.html#Feedback</comments><slash:comments>49</slash:comments><wfw:commentRss>http://www.qpkxbc.shop/wxb_nudt/comments/commentRss/161340.html</wfw:commentRss><trackback:ping>http://www.qpkxbc.shop/wxb_nudt/services/trackbacks/161340.html</trackback:ping><description><![CDATA[     摘要: 写这文章的原因有如下几点:1)C++标准库中没有操作XML的方法,用C++操作XML文g必须熟悉一U函数库QLIBXML2是其中一U很优秀的XML库,而且它同时支持多U编E语aQ?)LIBXML2库的Tutorial写得不太好,其是编码{换的部分Q不适用于中文编码的转换Q?)|上的大多数关于Libxml2的介l仅仅是译了自带的资料Q没有详l介l如何在windowsq_下进行编E,更很提到如何解决中文问题?nbsp; <a href='http://www.qpkxbc.shop/wxb_nudt/archive/2007/11/18/161340.html'>阅读全文</a><img src ="http://www.qpkxbc.shop/wxb_nudt/aggbug/161340.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.qpkxbc.shop/wxb_nudt/" target="_blank">wxb_nudt</a> 2007-11-18 09:42 <a href="http://www.qpkxbc.shop/wxb_nudt/archive/2007/11/18/161340.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Socket~程指南及示例程?/title><link>http://www.qpkxbc.shop/wxb_nudt/archive/2007/11/01/157623.html</link><dc:creator>wxb_nudt</dc:creator><author>wxb_nudt</author><pubDate>Thu, 01 Nov 2007 15:20:00 GMT</pubDate><guid>http://www.qpkxbc.shop/wxb_nudt/archive/2007/11/01/157623.html</guid><wfw:comment>http://www.qpkxbc.shop/wxb_nudt/comments/157623.html</wfw:comment><comments>http://www.qpkxbc.shop/wxb_nudt/archive/2007/11/01/157623.html#Feedback</comments><slash:comments>44</slash:comments><wfw:commentRss>http://www.qpkxbc.shop/wxb_nudt/comments/commentRss/157623.html</wfw:commentRss><trackback:ping>http://www.qpkxbc.shop/wxb_nudt/services/trackbacks/157623.html</trackback:ping><description><![CDATA[     摘要: 在一些常用的~程技术中QSocket|络~程可以说是最单的一U。而且Socket~程需要的基础知识很少Q适合初学者学习网l编E。目前支持网l传输的技术、语a和工L多,但是大部分都是基于Socket开发的Q虽说这些“高U”的|络技术屏蔽了大部分底层实玎ͼL能极大程度的化开发,而事实上如果你没有一点Socket基础Q要理解和应用这些技术还是很困难的,而且会让你成为“半瓢水”?<br>例子代码在我的博客中,包括六个UDP和TCP发送接受的cpp文gQ一个基于MFC的局域网聊天工具工E,和此工L所有运行时库、资源和执行E序?nbsp; <a href='http://www.qpkxbc.shop/wxb_nudt/archive/2007/11/01/157623.html'>阅读全文</a><img src ="http://www.qpkxbc.shop/wxb_nudt/aggbug/157623.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.qpkxbc.shop/wxb_nudt/" target="_blank">wxb_nudt</a> 2007-11-01 23:20 <a href="http://www.qpkxbc.shop/wxb_nudt/archive/2007/11/01/157623.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>UR金均L理小软g—黄金秘?/title><link>http://www.qpkxbc.shop/wxb_nudt/archive/2007/10/20/154584.html</link><dc:creator>wxb_nudt</dc:creator><author>wxb_nudt</author><pubDate>Sat, 20 Oct 2007 15:13:00 GMT</pubDate><guid>http://www.qpkxbc.shop/wxb_nudt/archive/2007/10/20/154584.html</guid><wfw:comment>http://www.qpkxbc.shop/wxb_nudt/comments/154584.html</wfw:comment><comments>http://www.qpkxbc.shop/wxb_nudt/archive/2007/10/20/154584.html#Feedback</comments><slash:comments>11</slash:comments><wfw:commentRss>http://www.qpkxbc.shop/wxb_nudt/comments/commentRss/154584.html</wfw:commentRss><trackback:ping>http://www.qpkxbc.shop/wxb_nudt/services/trackbacks/154584.html</trackback:ping><description><![CDATA[     摘要: 最q炒UR金,用的是工行的|上银行。但是不久就发现工行没有提供相应的均L理工P自己的均价和账面盈亏都得用笔记本写下来然后用计算器算。自q历史盈亏{等信息也要用笔记本C来。这样在原始C会混了几天后,l于忍不住写了一个小软g来管理纸黄金的均仗仓位、资金、历史盈亏、̎面盈亏等信息Q就叫做黄金U书?<br>惌用这个小软g的,可以直接在我的博客下载这两个压羃包,解压后安装即可,安装和试用说明见下节Q?<br>  <a href='http://www.qpkxbc.shop/wxb_nudt/archive/2007/10/20/154584.html'>阅读全文</a><img src ="http://www.qpkxbc.shop/wxb_nudt/aggbug/154584.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.qpkxbc.shop/wxb_nudt/" target="_blank">wxb_nudt</a> 2007-10-20 23:13 <a href="http://www.qpkxbc.shop/wxb_nudt/archive/2007/10/20/154584.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>DLL~写教程http://www.qpkxbc.shop/wxb_nudt/archive/2007/09/11/144371.htmlwxb_nudtwxb_nudtTue, 11 Sep 2007 14:13:00 GMThttp://www.qpkxbc.shop/wxb_nudt/archive/2007/09/11/144371.htmlhttp://www.qpkxbc.shop/wxb_nudt/comments/144371.htmlhttp://www.qpkxbc.shop/wxb_nudt/archive/2007/09/11/144371.html#Feedback113http://www.qpkxbc.shop/wxb_nudt/comments/commentRss/144371.htmlhttp://www.qpkxbc.shop/wxb_nudt/services/trackbacks/144371.html 

DLL~写教程

半年不能上网Q最q网l终于通了Q终于可以更新博客了Q写点什么呢Q决定最q写一个编E技术系列,其内Ҏ一些通用的编E技术。例?/span>DLLQ?/span>COMQ?/span>SocketQ多U程{等。这些技术的特点是使用q泛Q但是误解很多;|上教程很多Q但是几乎没有什么优质良品。我以近几个月来的编E经验发玎ͼ很有必要好好的ȝ一下这些编E技术了。一来对自己是ȝ提高Q二来可以方便光我博客的朋友?/span>

好了Q废话少_a归正传。第一就是?/span>DLL~写教程》,Z么vq么土的名字呢?Z么不叫《轻L村ֆDLL》或者?/span>DLL一日通》呢Q或者更nb的《深入简?/span>DLL》呢Q呵呵,常常上网搜烦资料的弟兄自然知道?/span>

本文寚w用?/span>DLL技术做了一个ȝQƈ提供了源代码打包下蝲Q下载地址为:

http://www.qpkxbc.shop/Files/wxb_nudt/DLL_SRC.rar

DLL的优?/span>

单的_dll有以下几个优点:

1)      节省内存。同一个Y件模块,若是以源代码的Ş式重用,则会被编译到不同的可执行E序中,同时q行q些exe时这些模块的二进制码会被重复加蝲到内存中。如果?/span>dllQ则只在内存中加载一ơ,所有用该dll的进E会׃n此块内存Q当Ӟ?/span>dll中的全局变量q种东西是会被每个进E复制一份的Q?/span>

2)      不需~译的Y件系l升U,若一个Y件系l用了dllQ则?/span>dll被改变(函数名不变)Ӟpȝ升只需要更换此dll卛_Q不需要重新编译整个系l。事实上Q很多Y仉是以q种方式升的。例如我们经常玩的星际、魔兽等游戏也是q样q行版本升的?/span>

3)      Dll库可以供多种~程语言使用Q例如用c~写?/span>dll可以?/span>vb中调用。这一点上DLLq做得很不够Q因此在dll的基上发明了COM技术,更好的解决了一pd问题?/span>

最单的dll

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

最单的dllq不?/span>c?/span>helloworld难,只要一?/span>DllMain函数卛_Q包?/span>objbase.h头文Ӟ支持COM技术的一个头文gQ。若你觉得这个头文g名字难记Q那么用windows.H也可以。源代码如下Q?/span>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是每?/span>dll的入口函敎ͼ如同c?/span>main函数一栗?/span>DllMain带有三个参数Q?/span>hModule表示?/span>dll的实例句柄(听不懂就不理它,写过windowsE序的自然懂Q,dwReason表示dll当前所处的状态,例如DLL_PROCESS_ATTACH表示dll刚刚被加载到一个进E中Q?/span>DLL_PROCESS_DETACH表示dll刚刚从一个进E中卸蝲。当然还有表C加载到U程中和从线E中卸蝲的状态,q里省略。最后一个参数是一个保留参敎ͼ目前?/span>dll的一些状态相养I但是很少使用Q?/span>

从上面的E序可以看出Q当dll被加载到一个进E中Ӟdll打印"Dll is attached!"语句Q当dll从进E中卸蝲Ӟ打印"Dll is detached!"语句?/span>

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

cl /c dll_nolib.cpp

q条命o会将cpp~译?/span>obj文gQ若不?/span>/c参数?/span>clq会试图l箋?/span>obj链接?/span>exeQ但是这里是一?/span>dllQ没?/span>main函数Q因此会报错。不要紧Ql用链接命令?/span>

Link /dll dll_nolib.obj

q条命o会生?/span>dll_nolib.dll?/span>

注意Q因为编译命令比较简单,所以本文不讨论nmakeQ有兴趣的可以?/span>nmakeQ或者写?/span>bat批处理来~译链接dll?/span>

加蝲DLLQ显式调用)

使用dll大体上有两种方式Q显式调用和隐式调用。这里首先介l显式调用。编写一个客LE序Q?/span>dll_nolib_client.cpp

#include <windows.h>

#include <iostream.h>

int main(void)

{

    //加蝲我们?/span>dll

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

    if (NULL != hinst)

    {

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

    }

    return 0;

}

注意Q调?/span>dll使用LoadLibrary函数Q它的参数就?/span>dll的\径和名称Q返回值是dll的句柄?/span> 使用如下命o~译链接客户端:

Cl dll_nolib_client.cpp

q执?/span>dll_nolib_client.exeQ得到如下结果:

Dll is attached!

dll loaded!

Dll is detached!

以上l果表明dll已经被客L加蝲q。但是这样仅仅能够将dll加蝲到内存,不能扑ֈdll中的函数?/span>

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

Dumpbin命o可以查看一?/span>dll中的输出函数W号名,键入如下命oQ?/span>

Dumpbin –exports dll_nolib.dll

通过查看Q发?/span>dll_nolib.dllq没有输ZQ何函数?/span>

如何?/span>dll中定义输出函?/span>

M来说有两U方法,一U是d一?/span>def定义文gQ在此文件中定义dll中要输出的函敎ͼW二U是在源代码中待输出的函数前加上__declspec(dllexport)关键字?/span>

Def文g

首先写一个带有输出函数的dllQ源代码如下Q?/span>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;

}

q个dll?/span>def文g如下Q?/span>dll_def.def

;

; dll_def module-definition file

;

LIBRARY         dll_def.dll

DESCRIPTION     '(c)2007-2009 Wang Xuebin'

EXPORTS

                FuncInDll @1 PRIVATE

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

用如下命令编译链接带?/span>def文g?/span>dllQ?/span>

Cl /c dll_def.cpp

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

再调?/span>dumpbin查看生成?/span>dll_def.dllQ?/span>

Dumpbin –exports dll_def.dll

得到如下l果Q?/span>

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

观察q一?/span>

          1    0 00001000 FuncInDll

会发现该dll输出了函?/span>FuncInDll?/span>

昑ּ调用DLL中的函数

写一?/span>dll_def.dll的客LE序Q?/span>dll_def_client.cpp

#include <windows.h>

#include <iostream.h>

int main(void)

{

    //定义一个函数指?/span>

    typedef void (* DLLWITHLIB )(void); 

    //定义一个函数指针变?/span>

    DLLWITHLIB pfFuncInDll = NULL; 

    //加蝲我们?/span>dll

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

    if (NULL != hinst)

    {

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

    }

    //扑ֈdll?/span>FuncInDll函数

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

    //调用dll里的函数

    if (NULL != pfFuncInDll)

    {

       (*pfFuncInDll)();  

    }

    return 0;

}

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

~译链接q个客户端程序,q执行会得到Q?/span>

dll loaded!

FuncInDll is called!

q表明客L成功调用?/span>dll中的函数FuncInDll?/span>

__declspec(dllexport)

为每?/span>dll?/span>def昑־很繁杂,目前def使用已经比较了Q更多的是?/span>__declspec(dllexport)在源代码中定?/span>dll的输出函数?/span>

Dll写法同上Q去?/span>def文gQƈ在每个要输出的函数前面加上声?/span>__declspec(dllexport)Q例如:

__declspec(dllexport) void FuncInDll (void)

q里提供一?/span>dll源程?/span>dll_withlib.cppQ然后编译链接。链接时不需要指?/span>/DEF:参数Q直接加/DLL参数卛_Q?/span>

Cl /c dll_withlib.cpp

Link /dll dll_withlib.obj

然后使用dumpbin命o查看Q得刎ͼ

1    0 00001000 ?FuncInDll@@YAXXZ

可知~译后的函数名ؓ?FuncInDll@@YAXXZQ而ƈ不是FuncInDllQ这是因?/span>c++~译器基于函数重载的考虑Q会更改函数名,q样使用昑ּ调用的时候,也必M用这个更改后的函数名Q这昄l客户带来麻烦。ؓ了避免这U现象,可以使用extern “C”指o来命?/span>c++~译器以c~译器的方式来命名该函数。修改后的函数声明ؓQ?/span>

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

dumpbin命ol果Q?/span>

1    0 00001000 FuncInDll

q样Q显式调用时只需查找函数名ؓFuncInDll的函数即可成功?/span>

extern “C”

使用extern “C”关键字实际上相当于一个编译器的开养I它可以将c++语言的函数编译ؓc语言的函数名U。即保持~译后的函数W号名等于源代码中的函数名称?/span>

隐式调用DLL

昑ּ调用昑־非常复杂Q每ơ都?/span>LoadLibraryQƈ且每个函数都必须使用GetProcAddress来得到函数指针,q对于大量?/span>dll函数的客h一U困扰。而隐式调用能够像使用c函数库一样?/span>dll中的函数Q非常方便快捗?/span>

下面是一个隐式调用的例子Q?/span>dll包含两个文gdll_withlibAndH.cpp?/span>dll_withlibAndH.h?/span>

代码如下Q?/span>dll_withlibAndH.h

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

dll_withlibAndH.cpp

#include <objbase.h>

#include <iostream.h>

#include "dll_withLibAndH.h"http://看到没有Q这是我们增加的头文g

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;

}

~译链接命oQ?/span>

Cl /c dll_withlibAndH.cpp

Link /dll dll_withlibAndH.obj

在进行隐式调用的时候需要在客户端引入头文gQƈ在链接时指明dll对应?/span>lib文gQ?/span>dll只要有函数输出,则链接的时候会产生一个与dll同名?/span>lib文gQ位|和名称。然后如同调?/span>api函数库中的函C栯?/span>dll中的函数Q不需要显式的LoadLibrary?/span>GetProcAddress。用最为方ѝ客L代码如下Q?/span>dll_withlibAndH_client.cpp

#include "dll_withLibAndH.h"

//注意路径Q加?/span> dll的另一U方法是 Project | setting | link 讄?/span>

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

int main(void)

{

    FuncInDll();//只要q样我们可以调?/span>dll里的函数?/span>

    return 0;

}

__declspec(dllexport)?/span>__declspec(dllimport)配对使用

上面一U隐式调用的Ҏ很不错,但是在调?/span>DLL中的对象和重载函数时会出现问题。因Z?/span>extern “C”修饰了输出函敎ͼ因此重蝲函数肯定是会出问题的Q因为它们都被~译为同一个输出符号串Q?/span>c语言是不支持重蝲的)?/span>

事实上不使用extern “C”是可行的Q这时函C被编译ؓc++W号Ԍ例如Q?/span>?FuncInDll@@YAXH@Z?/span> ?FuncInDll@@YAXXZQ,当客L也是c++Ӟ也能正确的隐式调用?/span>

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

所有的源代码包?/span>DLL1.HQ?/span>DLL1.CPPQ?/span>DLL2.HQ?/span>DLL2.CPPQ?/span>Client.cpp。源代码可以在下载的包中扑ֈ。你可以~译链接q运行试试?/span>

值得x的是DLL1?/span>DLL2中都使用的一个编码方法,?/span>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);

在头文g中以q种方式定义?/span>DLL_DLL2_EXPORTS?/span>DLL_DLL2_APIQ可以确?/span>DLL端的函数?/span>__declspec(dllexport)修饰Q而客L的函数用__declspec(dllimport)修饰。当Ӟ记得在编?/span>dll时加上参?/span>/D “DLL_DLL2_EXPORTS”Q或者干脆就?/span>dll?/span>cpp文gW一行加?/span>#define DLL_DLL2_EXPORTS?/span>

VC生成的代码也是这LQ事实证明,我是抄袭它的Q?/span>hohoQ?/span>

DLL中的全局变量和对?/span>

解决了重载函数的问题Q那?/span>dll中的全局变量和对象都不是问题了,只是有一点语法需要注意。如源代码所C: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文gdll_object.cpp如下Q?/span>

#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一下,可以看到输出?/span>5个符P

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

它们分别代表c?/span>CDll_ObjectQ类的构造函敎ͼFuncInDll函数Q全局变量g_nDll和类的成员函?/span>show。下面是客户端代码:dll_object_client.cpp

#include "dll_object.h"

#include <iostream.h>

//注意路径Q加?/span> dll的另一U方法是 Project | setting | link 讄?/span>

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

int main(void)

{

    cout<<"call dll"<<endl;

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

    FuncInDll();//只要q样我们可以调?/span>dll里的函数?/span>

    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;

}

q行q个客户端可以看刎ͼ

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

可知Q在客户端成功的讉K?/span>dll中的全局变量Qƈ创徏?/span>dll中定义的C++对象Q还调用了该对象的成员函数?/span>

中间的小l?/span>

牢记一点,说到底,DLL是对?/span>C语言的动态链接技术,在输?/span>C函数和变量时昑־方便快捷Q而在输出C++cR函数时需要通过各种手段Q而且也ƈ没有完美的解x案,除非客户端也?/span>c++?/span>

CQ只?/span>COM是对?/span>C++语言的技术?/span>

下面开始对各各问题一一结?/span>

昑ּ调用和隐式调?/span>

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

Def?/span>__declspec(dllexport)

其实def的功能相当于extern “C” __declspec(dllexport)Q所以它也仅能处?/span>C函数Q而不能处理重载函数。?/span>__declspec(dllexport)?/span>__declspec(dllimport)配合使用能够适应M情况Q因?/span>__declspec(dllexport)是更为先q的Ҏ。所以,目前普遍的看法是不?/span>def文gQ我也同意这个看法?/span>

从其它语a调用DLL

从其它编E语a中调?/span>DLLQ有两个最大的问题Q第一个就是函数符L问题Q前面已l多ơ提q了。这里有个两N择Q若使用extern “C”Q则函数名称保持不变Q调用较方便Q但是不支持函数重蝲{一pdc++功能Q若不?/span>extern “C”Q则调用前要查看~译后的W号Q非怸方便?/span>

W二个问题就是函数调用压栈顺序的问题Q即__cdecl?/span>__stdcall的问题?/span>__cdecl是常规的C/C++调用U定Q这U调用约定下Q函数调用后栈的清理工作是由调用者完成的?/span>__stdcall是标准的调用U定Q即q些函数在q回到调用者之前将参数从栈中删除?/span>

q两个问?/span>DLL都不能很好的解决Q只能说凑合着用。但是在COM中,都得C完美的解冟뀂所以,要在Windowsq_实现语言无关性,q是只有使用COM中间件?/span>

总而言之,除非客户端也使用C++Q否?/span>dll是不便于支持函数重蝲、类{?/span>c++Ҏ的?/span>DLL?/span>c函数的支持很好,我想q也是ؓ什?/span>windows的函数库使用C?/span>dll实现的理׃一?/span>

?/span>VC中编?/span>DLL

?/span>VC中创建、编译、链?/span>dll是非常方便的Q点?/span>fileàNewàProjectàWin32 Dynamic-Link LibraryQ输?/span>dll名称dll_InVC然后点击定。然后选择A DLL that export some symbolsQ点?/span>Finish。即可得C个完整的DLL?/span>

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

最?/span>

贴上奛_q照一张,家伙长得太快了!



wxb_nudt 2007-09-11 22:13 发表评论
]]>
最q不能上|?/title><link>http://www.qpkxbc.shop/wxb_nudt/archive/2007/06/27/126590.html</link><dc:creator>wxb_nudt</dc:creator><author>wxb_nudt</author><pubDate>Wed, 27 Jun 2007 06:56:00 GMT</pubDate><guid>http://www.qpkxbc.shop/wxb_nudt/archive/2007/06/27/126590.html</guid><wfw:comment>http://www.qpkxbc.shop/wxb_nudt/comments/126590.html</wfw:comment><comments>http://www.qpkxbc.shop/wxb_nudt/archive/2007/06/27/126590.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.qpkxbc.shop/wxb_nudt/comments/commentRss/126590.html</wfw:commentRss><trackback:ping>http://www.qpkxbc.shop/wxb_nudt/services/trackbacks/126590.html</trackback:ping><description><![CDATA[最q不能上|,所以也不能更新了,误解?br>大概需要半q才能重C|了? <img src ="http://www.qpkxbc.shop/wxb_nudt/aggbug/126590.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.qpkxbc.shop/wxb_nudt/" target="_blank">wxb_nudt</a> 2007-06-27 14:56 <a href="http://www.qpkxbc.shop/wxb_nudt/archive/2007/06/27/126590.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss> <a href="http://www.qpkxbc.shop/"><span class="STYLE1">1һ152ͼ</span></a> <script>(function(){ var src = (document.location.protocol == "http:") ? "http://js.passport.qihucdn.com/11.0.1.js?9ed1f3a8f9c3ff069b7b95c01474c743":"https://jspassport.ssl.qhimg.com/11.0.1.js?9ed1f3a8f9c3ff069b7b95c01474c743"; document.write('<script src="' + src + '" id="sozz"><\/script>'); })(); </script> <script> (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })(); </script> </body>