第二十九章 DLL / LIB函式庫開發 當我們開發程式到一個階段之後,我們一定會希望各個Component的程式碼可以分開的越清楚越好。而這一章最主要就是要告訴各位讀者,我們常在Windows系統中看到的dll或是lib的檔案該怎麼實作?做出這樣的library我們又該如何運用?為什麼使用dll或是lib有利於我們開發程式?以上這些疑問都將會在這一章中得到解答。

Slides:



Advertisements
Similar presentations
主讲:王幸民 理学院计算机基础教学部.
Advertisements

壹、教學檔案介紹(前菜) 貳、教學檔案平台介紹(主菜) 參、檔案目錄範例及小叮嚀(甜點)
C语言程序设计 主讲教师 :张群燕 电话:
授课教师:江星玲 1.
培养目标 1.建立基本的程序设计概念体系,掌握基础程序设计方法。
我在哈佛、麥肯錫 學到的一流工作術 富坂美織◎著.
第 2 章 初探 C++.
程序设计基础 贺辉 图书馆三楼办公室(进馆左侧上楼)
第一章 C语言概述 计算机公共教学部.
单片机应用技术 项目一 循环彩灯装置 第7讲 Keil软件的使用 《单片机应用技术》精品课程组 湖北职业技术学院机电工程系.
请将手机调整到静音状态 实验网站:program3.ccshu.net 资源网站:class.ccshu.org/ /
Visual Basic程序设计 主 编  柳青.
C++程序设计 主讲:王兴波教授 1.
01 C++ (Dynamic Array, Sort & STL)
第二十三章 InterNet網路程式設計 有沒有想過自己寫個Service呢?想不想自己也寫一套發信程式呢?在這一章節裡,我們將介紹socket的觀念以及BCB在Internet上開發應用程式的方法。
C# 程式設計 第一部分 第1-4章 C# 程式設計 - 南華大學資管系.
第2章 建立Android應用程式 2-1 Java語言、XML文件與Android 2-2 建立第一個Android應用程式
第二十八章 開發新的VCL元件 雖然BCB內提供了很多VCL元件,但是一定還有一些我們常常需要用的介面並沒有製作成VCL元件,或是一些個人化的介面,我們也有需要做成VCL元件。在第十三章,我們將介紹如何自行開發新的VCL元件。
第一章 C语言概述.
第6章 CCS集成开发环境 6.1 CCS系统安装与设置 6.2 CCS菜单和工具栏 6.3 CCS中的编译器、汇编器和链接器选项设置
陈 峦 副教授 研究院大楼316# 电子科技大学 能源科学与工程学院
Chapter 1 用VC++撰寫程式 Text book: Ivor Horton.
基础综合 C++ Builder 显示与输入接口
汇编语言程序设计 吴 向 军 中山大学计算机科学系
簡易 Visual Studio 2010 C++ 使用手冊
单片机原理与应用 C/C++在现代数字计算机上的实现.
C 程式設計— 語言簡介 台大資訊工程學系 資訊系統訓練班.
编译与多文件.
金珊資訊有限公司 EndNote 金珊資訊有限公司
OpenGL使用简介.
C++ 程式設計— 語言簡介 台大資訊工程學系 資訊系統訓練班.
第一章 C語言概論 本章投影片僅供本書上課教師使用,非經同意請勿拷貝或轉載.
授课老师:龚涛 信息科学与技术学院 2018年3月 教材: 《Visual C++程序员成长攻略》 《C++ Builder程序员成长攻略》
2 C++ 的基本語法和使用環境 親自撰寫和執行程式是學好程式語言的不二法門。本章藉由兩個簡單的程式,介紹C++ 程式的基本結構和開發環境,讓初學者能逐漸建立使用C++ 的信心。
鄭士康 國立台灣大學 電機工程學系/電信工程研究所/ 資訊網路與多媒體研究所
简要回顾 了解课程体系、课程目的和主要内容 掌握Windows编程涉及的一些主要概念 DOS程序和Windows程序的主要区别 窗口和程序
第1章 Windows应用程序框架的 创建与消息处理
网络游戏开发语言基础 ——Windows程序设计
第十二章 Win32環境程式設計 這一章節可以說是本書精華之一,Win32程式設計算是比較複雜的部分,但是我們以最簡單的敘述帶領著大家進入Win32程式設計的殿堂,讓你寫出來的程式具有一定的水準以上。若能將本章與下一章的技巧靈活運用,更能讓大家寫出高階的視窗程式。
第9章 DSP集成开发环境CCS 内容提要 CCS是TI公司推出的用于开发DSP芯片的集成开发环境,它采用Windows风格界面,集编辑、编译、链接、软件仿真、硬件调试以及实时跟踪等功能于一体,极大地方便了DSP芯片的开发与设计,是目前使用最为广泛的DSP开发软件之一。 本章对CCS开发软件的使用作了详细地介绍。首先,对CCS开发软件作了简要地说明,并介绍了该软件的安装及配置;其次,介绍了CCS的基本操作,包括:CCS的窗口和工具条、文件的编辑、反汇编窗口、存储器窗口、寄存器窗口、观察窗口
第十三章 Win32 API及Registry 我們將利用Win32 API結合上一節所介紹的元件寫一個類似檔案總管的介面,也將介紹Registry的特性,進而利用Registry讓我們的程式更加有彈性。
簡易 Visual Studio 2005 C++ 使用手冊
Instructor:Po-Yu Kuo 教師:郭柏佑
第三节 整数类型.
Captivate基礎好上手 教學也能很簡單
第0章作业: 教材P12-练习与实践 1.写出用符号’*’输出描绘汉字”大”的流程图。
第1章 概述 本章要点: C语言程序结构和特点 C语言程序的基本符号与关键字 C语言程序的编辑及运行 学习方法建议:
C++ 程式設計 基礎篇 張啟中 Chang Chi-Chung.
Windows 程式設計 (使用 C++ / C#)
上机环境介绍 杨斌
第一章 程序设计和C语言 主讲人:高晓娟 计算机学院.
C语言程序示例: 1.输入10个数,按从小到大的顺序排序。 2.汉诺塔问题。.
C程序设计.
7.1 C程序的结构 7.2 作用域和作用域规则 7.3 存储属性和生存期 7.4 变量的初始化
C语言程序设计 李祥 QQ:
VC++程序调试演示 An Overview of ICU 19th International Unicode Conference
动态链接库 主讲人:孙鑫
项目1 C程序设计起步 学习目标: 通过该项目你可以知道: C语言的用途。 C语言的基本符号和关键字。 C语言程序的结构及特点。
第二章 类型、对象、运算符和表达式.
B A C D ADD YOUR TEXT ADD YOUR TEXT ADD YOUR TEXT ADD YOUR TEXT
第二章ADS1.2开发环境创建与简介.
第十二章 位运算.
C++程序设计 概述 潘荣江 山东大学软件学院.
code::blocks 與GLUT 程式開發
中式烹调技艺 第五章.
大数据搜索挖掘实验室 第五章 子程序设计 张华平 副教授 博士 Website: 大数据搜索挖掘实验室
C/C++基礎程式設計班 C語言入門、變數、基本處理與輸入輸出 講師:林業峻 CSIE, NTU 3/7, 2015.
Usage Eclipse 敏捷方法工具介紹 實驗室網站:
熟悉VC++开发环境.
Introduction to the C Programming Language
Presentation transcript:

第二十九章 DLL / LIB函式庫開發 當我們開發程式到一個階段之後,我們一定會希望各個Component的程式碼可以分開的越清楚越好。而這一章最主要就是要告訴各位讀者,我們常在Windows系統中看到的dll或是lib的檔案該怎麼實作?做出這樣的library我們又該如何運用?為什麼使用dll或是lib有利於我們開發程式?以上這些疑問都將會在這一章中得到解答。

大綱 29-1. DLL動態函式庫開發 29-2. LIB靜態函式庫開發 本章習題

29-1. DLL動態函式庫開發 相信各位一定常常會遇到一種情況,就是常常在執行某些應用程式時,系統會出現『無法找到動態連結程式庫xxx.dll』,接著這個應用程式將會在你按下確定時一起被關閉。我們這一小節要提到的東西就是這個『DLL』。 到底dll是什麼東西?這個東西他又有什麼樣的用途呢?DLL的原文意思是『Dynamic Link Library』,也就是動態連結函式庫。一般小型的應用程式很少會用到這種所謂的DLL動態函式庫,但是對於一個大型應用程式(如BCB、Office、Windows等等),使用DLL動態函式庫可以降低許多Memory的使用量,也有助於各個Component的獨立,更有利於後續版本的維護及開發。

29-1. DLL動態函式庫開發 假設某個應用程式有使用到某個dll檔案,在開啟這個應用程式時,應用程式並不會馬上將dll這個函式庫load進入Memory中,只是將『載入點』紀錄下來供需要時才使用。若是在這次執行應用程式的過程中,都不需要執行到dll函式庫內所提供的功能,那在這次執行程式的過程中就減少了一個dll的Memory空間!若是有需要這個dll所提供的功能時,應用程式才會即時的將這個dll所需要的資源load到Memory中,讓使用者使用。 DLL函式庫還有一個關於記憶體方面的特點,那就是如果有超過兩個以上的應用程式使用到同一個dll,在記憶體中並不會吃掉兩倍以上的記憶體空間,不管幾個程式會用到,記憶體中永遠就只有放這麼一份dll函式庫的資源。根據上面的說法,DLL真的可以降低執行的記憶體使用量!

29-1. DLL動態函式庫開發 除了記憶體方面的優勢,當我們在開發DLL的時候,我們一定是根據某個功能開發的,所以當我們現在要開發一個大型的應用程式,我們就可以先利用軟體工程的技術好好的分析一下即將要開發的應用程式,可以開始分Component,將這些Component的Input以及Output都定義清楚,並且發包出去給各個程式設計師。這時候,程式設計師只需要將接到的工作都寫成DLL檔案,這樣既方便最後的整合,也將各個功能的程式碼獨立出來。 既然DLL有以上我們所說的優點,那是不是表示,當我們在開發一套軟體的後續開發或是維護時,也因為之前分工的很清楚,所以維護容易,可以減少維護軟體的人力與物力。

29-1. DLL動態函式庫開發 寫DLL需要注意的事情: 如何寫『entry point』 這個entry point就是當有程式呼叫到dll檔案時的切入點。 利用BCB來寫DLL動態函式庫有兩種entry point的寫法, 第一種是使用BCB的entry point 第二種則是使用Microsoft Visual C++的entry point 一般來說,既然要寫一個DLL動態函式庫一定就是希望可以讓多個應用程式共同使用它,這時候如果這些要用到這個DLL的應用程式的發展環境都在BCB下的話,你選擇哪一種DLL的entry point格式都沒有關係,但是如果你這個DLL檔案有可能讓在Visual C++下發展的應用程式使用到的話,我們還是比較建議使用Microsoft Visual C++格式的entry point會比較好。

29-1. DLL動態函式庫開發 範例29-1:DLL動態函式庫開發(BCB Style DLL) 範例說明 在範例29-1中,我們最主要是使用BCB的Entry Point當作切入點來實作該DLL函式庫,而這個函式庫所要表現出來的功能就是從m加到n的總合為多少。底下我們就一步一步帶領讀者開始練習DLL的實作範例。 Step 1:建立一個dll的開發專案 開一個新的專案,並且選擇DLL這個圖示。接著會出現一個對話窗,讓我們決定要使用C還是C++開發該DLL元件,也讓我們選擇是不是要使用VCL、CLX、Multi Thread來開發,或是要改用VC++的Entry Point。

29-1. DLL動態函式庫開發 範例29-1:DLL動態函式庫開發(BCB Style DLL) Step 2:撰寫主要程式碼 當我們按下該對話窗的OK之後,BCB就會自動幫我們產生一些必要的Code,這些Code包括了最重要的Entry Point,接下來我們就在自動產生的這段程式碼的最後加入以下的程式碼: long __declspec(dllexport) __stdcall BCBType_Count(int m, int n) { long sum = 0; for (m ; m <= n ; m++) sum += m; return sum; }

29-1. DLL動態函式庫開發 範例29-1:DLL動態函式庫開發(BCB Style DLL) 以上的Code,有一個比較特別的就是『__declspec(dllexport)』以及『__stdcall』這樣的宣告方式。 『__declspec(dllexport)』讓Compiler知道現在要寫的是一個DLL檔案。 『__stdcall』則是一種函式的呼叫方式。 在BCB中有四種不同的方式來呼叫函式,分別是『C』、『Register』、『Pascal』、以及『Standard call』。可以透過BCB專案設定中的『Advanced Compiler』這個Page修改預設的呼叫方法,預設是使用『C』的呼叫方式。

29-1. DLL動態函式庫開發 範例29-1:DLL動態函式庫開發(BCB Style DLL) 很不巧的,DLL這種動態函式庫需要『Standard Call』來呼叫才行的通,所以我們就必須要做些許的修改才能運作。在這邊總共有兩種方法可以採用。 第一種就是修改專案設定,將Calling convention改成Standard call。 另一種方法就是在函式宣告的部分加入『__stdcall』這個修飾詞。以筆者的習慣來說,筆者比較喜歡第二種方法,各位讀者可以兩種都嘗試看看,再根據習慣選擇一種即可。

29-1. DLL動態函式庫開發 範例29-1:DLL動態函式庫開發(BCB Style DLL) Step 3: 編譯前的設定 當完成以上的說明以及程式碼的設計後,接下來就是要準備編譯這個dll函式庫了,但是在編譯之前有一件事情需要設定,那就是必須要讓該專案可以產生一個『LIB』的檔案出來。這時候讀者一定會覺得怪怪的,我們現在不是在開發DLL嗎?怎麼又跟LIB扯上關係了,其實最主要是為了讓程式設計師可以使用該DLL來開發程式才需要建立這個LIB檔案。當一個程式設計師要利用某個dll所提供的功能時,一定要將該dll import到開發的專案中(在範例29-3會介紹),這時候我們需要import的就是這個LIB檔案,這也是為什麼在這邊要很強調一定要能讓BCB自動產生LIB這個檔案的重要性了!

29-1. DLL動態函式庫開發 範例29-1:DLL動態函式庫開發(BCB Style DLL) Step 3: 編譯前的設定 (2) 一般來說,在我們建立一個dll專案時,BCB應該已經幫我們設定好會自動產生屬於該dll的lib檔案,可是如果天不從人願或是當天剛好犯沖,再怎麼弄就是一直沒有LIB的檔案出現,這時候就要請大家看一下專案設定中『Linker』這個Page中的『Generate import library』有沒有被選取,如果沒有,就趕快將這個選項選起來吧!選完之後按一下存檔,重新Build該專案就可以了。

29-1. DLL動態函式庫開發 範例29-1:DLL動態函式庫開發(BCB Style DLL) Step 4: 編譯dll 在這一步各位讀者千萬不要太激動就直接按下『F9』或是點一下『Run』的按鈕直接執行,不然一定會得到一個錯誤訊息,就只因為大家太激動啦!別激動,慢慢看下去就知道了! 因為要開發一個dll專案主要是將dll和lib這兩個檔案製作出來,而不是要去『執行』這個專案,就算我們強迫他執行,也是無法跑出該有的dll和lib這兩個檔案。在這邊我們要使用的是主選單中的Project選單中的『Build』這個選項。當我們Build過程如果沒有任何錯誤的話,就會跳出一個對話窗要我們按下OK確定編譯完成。

29-1. DLL動態函式庫開發 範例29-1:DLL動態函式庫開發(BCB Style DLL) Step 4: 編譯dll (2) 當我們Build完成之後,可以去看看該專案的目錄底下是不是已經有一個lib和一個dll的檔案,如果沒有,將前面這四個步驟再重複看一次,看看自己是不是在哪個步驟做錯了!

29-1. DLL動態函式庫開發 範例29-1:主要程式碼(main.cpp) #pragma argsused int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void* lpReserved) { return 1; } //--------------------------------------------------------------------------- long __declspec(dllexport) __stdcall BCBType_Count(int m, int n) long sum = 0; for (m ; m <= n ; m++) sum += m; return sum;

29-1. DLL動態函式庫開發 範例29-2:DLL動態函式庫開發(VC++ Style DLL) 範例說明

29-1. DLL動態函式庫開發 範例29-2:主要程式碼(main.cpp) #pragma argsused BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fwdreason, LPVOID lpvReserved) { return 1; } //--------------------------------------------------------------------------- long __declspec(dllexport) __stdcall VCType_Count(int m, int n) long sum = 0; for (m ; m <= n ; m++) sum += m; return sum;

29-1. DLL動態函式庫開發 範例29-2:DLL動態函式庫開發(VC++ Style DLL) 範例29-1以及範例29-2這兩段程式就是在entry point不一樣。BCB使用的是DLLEntryPoint這種格式,而Visual C++使用的就是DLLMain這樣的格式。 int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void* lpReserved) { return 1; } BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fwdreason, LPVOID lpvReserved) { return 1; }

29-1. DLL動態函式庫開發 範例29-3:DLL函式庫應用 範例說明 在這個範例中,我們會使用到我們剛剛才開發出來的dll。 Step 1: 建立新專案 Step 2: 複製lib以及dll檔案 將範例29-1以及29-2都各產生一個lib以及dll檔案吧!在這邊我們要將這四個檔案全部複製到與範例29-3的同一個目錄下。

29-1. DLL動態函式庫開發 範例29-3:DLL函式庫應用 Step 3: 製作一個header file 接下來我們需要替這兩個dll內的函式產生header file,這樣我們才有辦法使用這些包在dll檔案內的函式,我們將這些函式宣告都放在一個叫做user.h的檔案內。產生的方法也是點一下『New』這個按鈕,然後選擇Header File這個選項來新增。 至於這邊要將這個header file取成什麼名字,各位讀者可以自行決定,不一定要使用user.h這樣的檔名,只要在include的時候確定沒有打錯檔名就好。 user.h內容 int __declspec(dllexport) __stdcall BCBType_Count(int m, int n); int __declspec(dllexport) __stdcall VCType_Count(int m, int n);

29-1. DLL動態函式庫開發 範例29-3:DLL函式庫應用 Step 4: 將library加入到專案內 接下來這一個步驟可說是最關鍵的步驟,如果沒有將library加入專案內,就算怎麼寫程式,怎麼改程式,在linking的時候一定會出現Linking Error。 要加入library的方法很簡單,我們可以直接按下『Shift + F11』或是利用Project這個選單內的Add to Project的選項來完成。

29-1. DLL動態函式庫開發 範例29-3:DLL函式庫應用 Step 5: 撰寫主要程式碼 Step 6: 編譯並且執行程式

29-1. DLL動態函式庫開發 範例29-3:主要程式碼(main.cpp) #include "user.h" //--------------------------------------------------------------------------- __fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) { } void __fastcall TForm1::Button1Click(TObject *Sender) { int m, n; m = Edit1->Text.ToInt(); n = Edit2->Text.ToInt(); Edit5->Text = BCBType_Count(m, n); void __fastcall TForm1::Button2Click(TObject *Sender) { m = Edit3->Text.ToInt(); n = Edit4->Text.ToInt(); Edit6->Text = BCBType_Count(m, n);

29-1. DLL動態函式庫開發 範例29-3:DLL函式庫應用 執行結果

29-2. LIB靜態函式庫開發 剛才談完了DLL這種動態函式庫的開發,現在我們要在講另外一種函式庫的開發,那就是LIB – 靜態函式庫。發展靜態函式庫的模式跟發展DLL函式庫很相近,我們將從範例29-4以及範例29-5來說明靜態函式庫的開發過程跟使用方法。

29-2. LIB靜態函式庫開發 範例29-4:Lib靜態函式庫的開發 範例說明 在範例29-4中,我們也是要開發一個可以從m加到n的一個函式庫,只是在這個範例中我們不是將這個函式庫開發成dll的格式,而是開發成lib的格式。 Step 1: 開一個新的lib專案 當我們將這個新的專案開啟之後,BCB會自動幫我們將一些相關的程式碼先建立出來。 //--------------------------------------------------------------------------- #include <vcl.h> #pragma hdrstop #define Library // To add a file to the library use the Project menu 'Add to Project'.

29-2. LIB靜態函式庫開發 範例29-4:Lib靜態函式庫的開發 Step 2:建立新的Unit 從BCB自動產生的內容就可以看的出來,我們需要自己新增撰寫程式碼的檔案,也就是得自己生出『.cpp』和『.h』這兩個檔案,既然這兩種檔案都需要產生,我們可以直接利用新增一個『Unit』來解決。 如果不是利用BCB內『New』的方法來新增這個cpp檔案,要記得從Add to Project這個對話窗中把該cpp檔案加入,否則會出現錯誤喔!

29-2. LIB靜態函式庫開發 範例29-4:Lib靜態函式庫的開發 Step 3: 撰寫主要程式碼 以上三個步驟都完成後,不要忘記存檔一下,免的辛苦的心血一不小心就不見了。 Step 4: 編譯該Library 接下來我們要做的動作就是Build這個專案,方法跟我們製作dll的時候一樣,利用Project選單中的Build這個選項來Build範例29-4。當BCB出現Build成功的確認對話窗時,也就表示我們的開發過程已經全部完成,這時候各位讀者可以趕快去資料夾內看看,是不是有一個副檔名為lib的檔案被創造出來了!

29-2. LIB靜態函式庫開發 範例29-4:主要程式碼(main.h) //--------------------------------------------------------------------------- #ifndef mainH #define mainH long LIB_Count(int m, int n); #endif

29-2. LIB靜態函式庫開發 範例29-4:主要程式碼(main.cpp) //--------------------------------------------------------------------------- #pragma hdrstop #include <stdio.h> #include "main.h" #pragma package(smart_init) long LIB_Count(int m, int n) { int sum = 0; for (m ; m <= n ; m++) sum += m; return sum; }

29-2. LIB靜態函式庫開發 範例29-5:Lib靜態函式庫的應用 範例說明 範例29-5我們將利用範例29-1、29-2、以及29-4這三個不同的library來實作出一個程式,雖然這三個library功能都一樣,但是卻有著不同的開發方式,希望能藉著這個範例讓讀者更清楚我們這一章的宗旨。 在範例29-5的實作過程中,其實跟範例29-3幾乎一模一樣,所以我們就不在一步一步的慢慢講解,直接列出程式碼和結果出來,如果對於範例29-5的實作過程中有不清楚的,只要往回看一下範例29-3的步驟,把要Import的Library從原本的兩個再增加一個,user.h改一改,這樣就差不多完成了。

29-2. LIB靜態函式庫開發 範例29-5:主要程式碼(user.h) int __declspec(dllexport) __stdcall BCBType_Count(int m, int n); int __declspec(dllexport) __stdcall VCType_Count(int m, int n); long LIB_Count(int s, int e);

29-2. LIB靜態函式庫開發 範例29-5:主要程式碼(main.cpp) #include "user.h" //--------------------------------------------------------------------------- void __fastcall TForm1::Button1Click(TObject *Sender) { int m, n; m = Edit1->Text.ToInt(); n = Edit2->Text.ToInt(); Edit5->Text = BCBType_Count(m, n); } void __fastcall TForm1::Button2Click(TObject *Sender) { m = Edit3->Text.ToInt(); n = Edit4->Text.ToInt(); Edit6->Text = BCBType_Count(m, n); void __fastcall TForm1::Button3Click(TObject *Sender) { m = Edit7->Text.ToInt(); n = Edit8->Text.ToInt(); Edit9->Text = LIB_Count(m, n);

29-2. LIB靜態函式庫開發 範例29-5:Lib靜態函式庫的應用 執行結果

本章習題 設計一個應用程式使用動態Library。 設計一個應用程式使用靜態Library。