﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>C++博客-shrimp-文章分类-Qt</title><link>http://www.cppblog.com/shrimp/category/17386.html</link><description /><language>zh-cn</language><lastBuildDate>Mon, 25 Jul 2011 14:27:23 GMT</lastBuildDate><pubDate>Mon, 25 Jul 2011 14:27:23 GMT</pubDate><ttl>60</ttl><item><title>ibrary跨平台调用动态库的实现 </title><link>http://www.cppblog.com/shrimp/articles/151820.html</link><dc:creator>shrimp</dc:creator><author>shrimp</author><pubDate>Mon, 25 Jul 2011 12:23:00 GMT</pubDate><guid>http://www.cppblog.com/shrimp/articles/151820.html</guid><wfw:comment>http://www.cppblog.com/shrimp/comments/151820.html</wfw:comment><comments>http://www.cppblog.com/shrimp/articles/151820.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/shrimp/comments/commentRss/151820.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/shrimp/services/trackbacks/151820.html</trackback:ping><description><![CDATA[1)win下动态库调用有关的函数包括： <br />(1)LoadLibrary，装载动态库。 <br />(2)GetProcAddress，获取要引入的函数，将符号名或标识号转换为DLL内部地址。 <br />(3)FreeLibrary，释放动态链接库。<br />2)unix上与动态库调用有关的函数包括：<br />(1)_打开动态链接库：dlopen，函数原型void *dlopen (const char *filename, int flag); <br />dlopen用于打开指定名字(filename)的动态链接库，并返回操作句柄。 <br />(2)取函数执行地址：dlsym，函数原型为: void *dlsym(void *handle, char *symbol); <br />dlsym根据动态链接库操作句柄(handle)与符号(symbol)，返回符号对应的函数的执行代码地址。 <br />(3)关闭动态链接库：dlclose，函数原型为: int dlclose (void *handle); <br />dlclose用于关闭指定句柄的动态链接库，只有当此动态链接库的使用计数为0时,才会真正被系统卸载。 <br />(4)动态库错误函数：dlerror，函数原型为: const char *dlerror(void); 当动态链接库操作函数执行失败时，dlerror可以返回出错信息，返回值为NULL时表示操作函数执行成功。 
<p>我们来分析下Qt的源代码，看看Qt是如何封装这两种不同的调用动态库的方法。</p>
<p>下面是我用vc编写的一个动态库中的函数add:<br />extern "C" __declspec(dllexport) int __stdcall add(int a,int b)<br />{<br />&nbsp;&nbsp;&nbsp; return a+b;<br />}</p>
<p>下面我就用QLibrary来调用一下：</p>
<p>QLibrary lib("QtDllTest.dll");<br />if (lib.load())<br />{<br />&nbsp;&nbsp;&nbsp; typedef int(*AddFunction)(int a,int b);<br />&nbsp;&nbsp;&nbsp; AddFunction Add=(AddFunction)lib.resolve("add");<br />&nbsp;&nbsp;&nbsp; if (!Add)<br />&nbsp;&nbsp;&nbsp; {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cout&lt;&lt;"failed"&lt;&lt;endl;<br />&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp; else<br />&nbsp;&nbsp;&nbsp; {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int m;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; m=Add(1,1); //来个计算1+1<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cout&lt;&lt;"result:"&lt;&lt;m&lt;&lt;endl;<br />&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp; lib.unload();<br />}<br />else<br />{<br />&nbsp;&nbsp;&nbsp; cout&lt;&lt;"failed"&lt;&lt;endl;<br />}</p>
<p><br />首先将目录切换到QTDIR/src/corelib/plugin，这里面就是QLibrary实现的源代码，打开qlibrary_p.h(熟悉了Qt的常用手法，就知道，这就是QLibrary内部实现的代码)，可以看到<br />&nbsp;&nbsp;&nbsp; bool load_sys();<br />&nbsp;&nbsp;&nbsp; bool unload_sys();<br />&nbsp;&nbsp;&nbsp; void *resolve_sys(const char *);<br />三个函数。在qlibrary.cpp中可以找到调用这三个函数的地方<br />bool QLibrary::load ()调用了load_sys；<br />bool QLibrary::unload ()调用了unload_sys；<br />void * QLibrary::resolve ( const char * symbol )调用了resolve_sys</p>
<p>但是并没有找到这三个函数的实现，这是这么回事呢？<br />打开QTDIR/src/corelib/plugin/plugin.pri文件，<br />win32 {<br />&nbsp;SOURCES += plugin/qlibrary_win.cpp<br />}</p>
<p>unix {<br />&nbsp;SOURCES += plugin/qlibrary_unix.cpp<br />}</p>
<p>原来如此啊。</p>
<p>我们仔细看下qlibrary_win.cpp文件，load_sys函数调用了LoadLibrary，unload_sys调用了FreeLibrary，resolve_sys调用了GetProcAddress。<br />而在qlibrary_unix.cpp文件中，各种linux平台又分好多种。但是基本上load_sys调用了dlopen，unload_sys调用了dlclose，resolve_sys调用了dlsym。<br />在HPUX中dlopen对应shl_load，dlclose对应shl_unload，dlsym对应shl_findsym。</p>
<p>原来QLibrary就是这样实现不同平台动态库的调用。</p><img src ="http://www.cppblog.com/shrimp/aggbug/151820.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/shrimp/" target="_blank">shrimp</a> 2011-07-25 20:23 <a href="http://www.cppblog.com/shrimp/articles/151820.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Qt解决方案中添加动态链接库项目</title><link>http://www.cppblog.com/shrimp/articles/151816.html</link><dc:creator>shrimp</dc:creator><author>shrimp</author><pubDate>Mon, 25 Jul 2011 11:37:00 GMT</pubDate><guid>http://www.cppblog.com/shrimp/articles/151816.html</guid><wfw:comment>http://www.cppblog.com/shrimp/comments/151816.html</wfw:comment><comments>http://www.cppblog.com/shrimp/articles/151816.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/shrimp/comments/commentRss/151816.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/shrimp/services/trackbacks/151816.html</trackback:ping><description><![CDATA[<p>动态链接的好处： 生成执行文件小，修改程序后重新编译部分少。<br />如何添加动态链接库项目：<br />解决方案-&gt;添加新建项目-&gt;qt projects -&gt; qt library （输入项目名为abc），然后生成一个新项目，包含abc.h abc.cpp abc_global.h三个文件，打开abc.h可以看到class ABC_EXPORT abc 的定义（在abc_global.h中有#define ABC_EXPORT Q_DECL_EXPORT，再次跟踪，有define Q_DECL_EXPORT __declspec(dllexport)，可能define的宏名不一样吧），再在abc.h删除类abc，加入<br />extern "C"<br />{<br />&nbsp;&nbsp;&nbsp; STATIC_EXPORT WndStatic* NewForm();&nbsp;&nbsp; //NewForm为导出函数<br />}<br />在abc.cpp中定义NewForm函数。<br />完成之后在原来的项目中调用QLibrary::resolve ("abc", "NewForm") ，Loads the library fileName and returns the address of the exported symbol symbol.返回类NewForm的指针。<br />typedef WndStatic* (*FUNC)();<br />&nbsp;&nbsp;&nbsp; FUNC func;<br />&nbsp;&nbsp;&nbsp; func = (FUNC)QLibrary::resolve("abc", "NewForm");<br />&nbsp;&nbsp;&nbsp; if (func)<br />&nbsp;&nbsp;&nbsp; {}<br />最后注意要在原来的项目中-&gt;属性-&gt;配置属性-&gt;c/c++-&gt;常规，附加包含目录中添加新项目所在的目录，然后在原项目中#include 相应的文件。</p>
<p>&nbsp;</p>
<p>＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝＝</p>
<p style="text-indent: 2em">对于调用DLL的方法，Qt原来本身就有相应的类来实现，用起来和Win32的步骤差不多。下面是代码，已经编译通过。在控制台依次输入qmake &#8211;project、qmake、 nmake，即可。</p>
<p style="text-indent: 2em">#include</p>
<p style="text-indent: 2em">#include</p>
<p style="text-indent: 2em">#include</p>
<p style="text-indent: 2em">// 动态链接不需要包含LTM8000D.h头文件</p>
<p style="text-indent: 2em">typedef int ( *pcom_open)(int , int , int ); //定义函数指针</p>
<p style="text-indent: 2em">int main(int argc, char *argv[])</p>
<p style="text-indent: 2em">{</p>
<p style="text-indent: 2em">int ret; //函数返回值</p>
<p style="text-indent: 2em">int port=1; //端口</p>
<p style="text-indent: 2em">int baud=0; //波特率</p>
<p style="text-indent: 2em">int rtsdtr=0; //串行口485方向控制设置:</p>
<p style="text-indent: 2em">QApplication a(argc, argv);</p>
<p style="text-indent: 2em">QLabel label1(&#8221;label-1&#8243;); //显示打印信息，将就着用了。。。</p>
<p style="text-indent: 2em">QLabel label2(&#8221;label-2&#8243;);</p>
<p style="text-indent: 2em">QLibrary mylib(&#8221;LTM8000D.DLL&#8221;);</p>
<p style="text-indent: 2em">if(mylib.load())</p>
<p style="text-indent: 2em">{</p>
<p style="text-indent: 2em">label1.setText(&#8221;load DLL success!&#8230;&#8221;);</p>
<p style="text-indent: 2em">pcom_open open=(pcom_open)mylib.resolve(&#8221;ltm_com_open&#8221;);//&#8220;ltm_com_open&#8221;为DLL包含的实际函数名，必须实际存在</p>
<p style="text-indent: 2em">if(open)</p>
<p style="text-indent: 2em">{ ret=open(port, baud, rtsdtr); //在这里调用DLL里的函数</p>
<p style="text-indent: 2em">label2.setText(&#8221;resolve ok&#8230;&#8221;);</p>
<p style="text-indent: 2em">}</p>
<p style="text-indent: 2em">else</p>
<p style="text-indent: 2em">{</p>
<p style="text-indent: 2em">label1.setText(&#8221;resolve failed&#8230;&#8221;);</p>
<p style="text-indent: 2em">}</p>
<p style="text-indent: 2em">}else</p>
<p style="text-indent: 2em">{</p>
<p style="text-indent: 2em">label2.setText(&#8221;load DLL failed&#8230;&#8221;);</p>
<p style="text-indent: 2em">}</p>
<p style="text-indent: 2em">label1.show();</p>
<p style="text-indent: 2em">label2.show();</p>
<p style="text-indent: 2em">return a.exec();</p>
<p style="text-indent: 2em">}</p>
<p style="text-indent: 2em">总结：类似于调用DLL的交叉编程使用的场合很多，还可以用Qt生成DLL，给其他工具调用。说到底，VC和Qt等本质上都是一样的，只是提供了不同的C++库<br /><br /><br />转文出处：<a href="http://blog.csdn.net/yavobo/article/details/5643466">http://blog.csdn.net/yavobo/article/details/5643466</a></p><img src ="http://www.cppblog.com/shrimp/aggbug/151816.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/shrimp/" target="_blank">shrimp</a> 2011-07-25 19:37 <a href="http://www.cppblog.com/shrimp/articles/151816.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>