1. 程式人生 > >C編譯器LCC-win32的使用介紹

C編譯器LCC-win32的使用介紹

LCC-Win32介紹
  LCC-Win32原來是一個免費的開放原始碼WIN32編譯器,包含一個很好用的IDE,
用起來很爽,但是最近原始碼開始要付費的了(40美圓)。詳情請見LCC-Win32官方網站。
它的免費版本可以在國內得到,到雲風工作室看一下,你會有所收穫。

目錄

  * 簡介
  * 編譯器的安裝
  * Lcc-Win32的一些基本概念
  * 寫個小程式!
  * 使用工程管理
  * 第一個Windows程式
  * 程式生成嚮導
  * 使用WeditRes建立資源
  * 新增其它型別的資源
  * 使用非規格資源
  * 靜態庫和動態庫
簡介
  其實所謂的簡介這個部分的內容趨向取決於作者。但是我所讀過的一些指南都是由
一個“簡介”開始的,這部分的內容通常都是在重複讀者會在下面看到的東西,但是也
有的簡介只是作者的一些想法。

  仔細的想一下,其實這個介紹並不是一件簡單的事情。首先,如果你要是開門見山
的直奔主題,這是不禮貌的,而且基於web的指南也不應該有超大個的簡介,不應該讓
讀者在這個東西上浪費時間和金錢。

  看來我的廢話也夠多的了,讓我們切入正題。

  這個指南是單頁的,建議你等瀏覽器下載完畢後儲存一份拷貝來離線閱讀。

編譯器的安裝
  編譯器的安裝簡單極了,只要把您下載的檔案執行一下就OK了,應該不會遇到什麼
問題。但是注意安裝的最後要編譯庫檔案,可能要花點時間,要視你的機器速度而定。
Lcc-Win32的一些基本概念
  Lcc-Win32編譯系統是由多個檔案構成的。它們的共同的任務是把文字格式的源代
碼編譯位可以執行的二進位制格式。優良個重要的檔案分別是編譯器(lcc.exe)和連線
器(lcclnk.exe)。

  編譯器是用來把你編寫的文字翻譯成處理器可以執行的格式的程式。聯結器用來轉
換編譯器生成的二進位制檔案(通常叫做目標檔案),並新增作業系統用來把程式調入內
存並執行所需要的資訊它可以把多個目標檔案連結為一個單獨的程可執行程式,這樣就
可以使你可以把一個程式的程式碼文件分割為幾個模組,這個能力在你開發大型程式時是
很重要的。

  雖然這些聽起來好像十分的簡單,但是實際上並不是這個樣子的。編輯器和連結器
需要你在命令列方式下鍵入你要建立的程式的所有資訊,這將需要你記住大量的命令列
引數和各種各樣的開關,這時就需要IDE——整合開發環境(wedit.exe)來提供方便了。

  IDE的基本功能是編輯文字,你可以在這個環境裡編輯程式的原始碼,但是遠遠不
止有這個功能。它還給你提供了一個呼叫編譯器和連結器的簡單方法,這樣在編譯程式
的時候你就不用去記住那麼多的命令列引數了。

  你可以簡單的把Wedit想象成你的控制檯,在這裡你可以控制所有的流程。
 好吧!現在你可以用你的滑鼠點一下Windows的“開始”按鈕,在程式項的子選單了
尋找“lcc-win32”,好了嗎?現在你已經準備好在Lcc-Win32中寫你的第一個程式了。

寫個小程式!
  你知道嗎?自從第一個C編譯器產生以來(也許可能更早一些),有一個慣例就是
為這個編譯器寫的第一個程式是“Hello World”,我為我擁有的所有編譯器都寫過,
現在我們就來寫一個。

  第一步是建立原始碼檔案。在“File”選單中選擇“new”項,然後在出現的對話方塊
中輸入“hello.c”並點一下“OK”。

  現在你看到的是一個標題為“hello.c”的空白視窗,輸入下面的程式碼:

#include <stdio.h>

void main (void)
{
  printf ("Hello World from LCC-Win32!/n");
}

  儲存我們的小程式,在“File”選單中選擇“Save”項。
 現在我們可以編譯這個程式了。選擇“Compiler”選單中的“Compile hello.c”
呼叫編譯器。這時一個新視窗會出現在IDE的底部,這是資訊視窗,當編譯器處理完成,
在這個視窗中將會顯示“HELLO.exe build successfully.”,如果編譯出錯,出錯信
息也將會被顯示在這裡。

  如果編譯出錯了,在資訊視窗處雙擊資訊顯示所在行,在編輯視窗內將高亮度顯示
出錯程式碼行,仔細的檢查一下你寫的程式和上面我寫的一樣,這裡需要注意的是C語言
是大小寫敏感的程式語言,這意味著“printf”和“Printf”對編譯器是不相同。

  現在你已經編譯好了這個程式,按[Ctrl]+[F5]鍵執行一下,結果對嗎?

使用工程管理
  現在你已經編譯了你的第一個程式,你可能想知道——執行檔案在哪裡?

  回答是:我也不知道!這可能聽起來很傻(的確也是),但是這是看你在編譯程式
時的預設目錄是什麼,所以你應該在你的硬盤裡搜尋一個叫做“hello.exe”的檔案。

  你肯定不會想要每開發一個程式都要搜尋一下硬碟的,這種情況下你就要使用工程。
  工程是一些編譯器要知曉的建立程式所需要的資訊。這包括程式原始檔、編譯好的
檔案的存放地點、要編譯為什麼型別的可執行檔案,一個好的想法是為每一個程式建立
一個工程。

  事實上,對於我們的“HelloWorld”程式還是有一個工程的,Lcc=Win32會為沒有
指明工程的程式建立一個預設的工程。選擇“Project”選單的“Erase...”項,Wedit
會顯示一個工程列表,你會看到一個專案叫做“HELLO”,現在我們毫不留情的刪除它。

  與其他的編譯器不同的是,Lcc-Win32的工程資訊不是儲存在硬碟上的,而是儲存
在Windows的登錄檔項裡。這使得Wedit可以“記住”所有的工程,甚至於在不同的磁碟
上。但是優勢我們也需要清除我們不再使用的工程,在這種情況下,我們可以把工程信
息匯出到磁碟上,然後在IDE中刪除它。看一下“Project”選單的選項,你就會明白了。

  現在你可以試著建立一個“HELLO”工程。
第一個Windows程式
  你可能已經注意到了hello.exe看起來象是一個DOS程式,但是它不是的,它是一個
真正Windows程式,但是這種型別的程式被稱為Windows控制檯程式,就是在文字模式下
執行的Windows程式。如果你不相信,可以試著在Windows的純DOS環境下執行一下,你
會得到一行資訊:“This program cannot be run in DOS mode”。

  寫一個真正的Windows版的“HelloWorld”程式並不比控制檯的版本難多少。首先
建立一個新工程,選擇“Windows executable”代替“Console application”,點OK
後,Lcc-Win32會問你需要Wizard(生成嚮導)建立程式框架嗎,回答No。

#include <windows.h>

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
  MessageBox (NULL, "Hello world from Lcc-Win32!", "Hello", MB_OK);
  return 0;
}

  編譯並執行這個程式,你會看到一個顯示hello資訊的視窗,點ok關閉退出。
不幸的是,除了這樣的小之又小的Windows程式,一般情況下Windows程式是很複雜
的,現在你已經知道了如何建立工程和編譯程式,如果你是一個Windows程式設計新手,去
找一些有關的書來看看,取得必要的基礎,一些Windows程式設計知識在下面的部分是必須
的。

  如果你是一個C語言的新手,那麼先好好的學一段時間再來看這個指南吧!

程式生成嚮導
  Windows程式與文字狀態下的程式比起來要好的多,但是天上不會掉餡餅的,你想
要得到的Windows功能支援,比如:剪裁板、多工等等要付出的是大量的複雜的程式碼。

  但是總還是有些辦法可以使事情變得簡單一些的。長時間以來,程式設計師們發現實際
上總是有些在每個程式中都相同的程式碼段,所以Windows程式設計師通常使用模板來生成這
部分程式碼。就是說原始檔一般只要生成一次,就可以在任何一個新程式中使用了。只有
變化的部分才是每個程式不同的部分,顯然這些應該是可以自動的進行的。

  這就是生成嚮導要完成的工作。你可以在它的幫助下快速的生成應用程式的框架。
這個框架事實上就是一個什麼功能也沒有的一個完整的程式,也許可能只是用來顯示一
個空窗體,因為使程式完成具體的功能是你的工作。

  讓我們看一下使用嚮導建立最簡單的應用程式的處理。
 通常,第一步是建立程式程式碼,然後建立一個工程。在使用嚮導的模式下,你並不
需要寫一行程式碼,嚮導將為你建立它,我們直接來看建立工程各個步驟。

  在“Project”選單下選擇“create”項,給出專案名稱和路徑,選擇工程型別為
“Windows executable”,當Wedit詢問你是否要使用嚮導(wizard),回答“yes”,
這樣就進入了嚮導模式。

  嚮導將顯示一個對話方塊叫做:“Application characteristics”,這是嚮導將在
應用程式中包含的基本特點,你可以選擇以下情況的一種:單視窗、多視窗和DLL(動
態連結庫),現在我們要建立一個十分簡單的單視窗小應用程式,選擇單視窗型別並確
保所有的特性複選按紐都未被選中,點選“OK”進行處理。

  現在嚮導將要提示你輸入資訊設定主視窗的“類”,這裡所說的“類”和C++中的
類是不同的,它是Windows在記憶體中儲存的一個結構,用來儲存正確顯示視窗所需要的
資訊。最重要的是“回叫函式”(下面將具體介紹)的名稱,現在只要簡單接受預設的
屬性值,點選“NEXT”進行處理。
 這個“Generate code for the main window creation”對話方塊用來設定相應視窗
的資訊。當主窗體被建立的時候這些資訊會被傳送到相應的視窗。在這裡你可以改變窗
口的標題欄的顯示內容,然後點選“Finish”。

  嚮導的工作就要完成了,接下來的工程建立工作是通常的一些對編譯器、連結器、
偵錯程式的一些設定,這裡只要簡單的接受預設的選項就可以了。

  經過上面的步驟,就完成了嚮導的所有的工作,你可以在IDE中看到兩個視窗,一
個是源程式編輯窗,另外的一個是用來定義應用程式的主選單的指令碼。

  正象剛剛所說的那樣,這個程式框架是全功能的,可以通過編譯並執行,你可以看
到一個有選單的視窗。唯一可以進行的操作是“File”選單的“Exit”項,你可以使用
這個選單項關閉這個簡單的視窗,也可以使用[Ctrl]+[Q]完成同樣的操作。

  現在你可以看一下這個程式的原始碼,你會注意到這個程式比那個“Hello World!”
程式複雜了許多,我可以告訴你一個小竅門——從原始碼的結尾開始讀起,因為通常那
裡才是一些功能函式的所在。

使用WeditRes建立資源
  在Windows程式的開發中,資源是十分重要的部分,選單、對話方塊和其它的一些用
戶介面部分都是可以象寫程式一樣的編寫的,可以簡單的作為資源包含程序序中。

  如果Lcc-Win32沒有提供一個資源編輯器那麼Lcc-Win32將不是一個完整的Win32編
譯程式,Lcc-Win32提供的資源編輯器叫做WeditRes,是在“lcc/bin/”路徑下。

  的確,WeditRes還是在不斷的完善的過程中,也就是說還沒有開發完成。不過它已
經可以編輯一些手工編輯難以完成的資源了,比如:選單和對話方塊等等。在IDE下呼叫
WeditRes,在“Compiler”選單下選擇“Resources”項。

  如果你正在開發的程式是用嚮導生成的,那麼嚮導會產生一個資原始檔,在這個文
件裡至少包括選單資源,WeditRes會開啟這個資原始檔,但是它不會找到相應的標頭檔案,
你應該為它指明標頭檔案的路徑。通常是在WeditRes當前工作路徑的上一級目錄。
WeditRes要找的檔案通常叫做prjnamewiz.h,這裡的prjname是你指定
的工程的名稱。經過這一步就可以修改工程所用的資源了。
如果你的程式不是由嚮導生成的,那麼WeditRes會提示你輸入資原始檔的檔名,輸
入一個名稱後點擊“OK”,這時WeditRes會說不能開啟這個資原始檔,沒有關係,這是
因為這個目錄下的確是沒有資原始檔的,還是在這個對話方塊中點選“OK”,然後在
“File”選單中選擇“New”項,這樣就會為你的工程建立一個新的資源工程,鍵入一
個工程名,一般情況是和應用程式的工程名相同,然後點選“Validate”,現在你需要
手工在應用程式工程列表裡新增這個資原始檔(一般以“RES”為副檔名)。

  在這裡試舉一例——我們來為我們上面建立的程式建立一個“關於”對話方塊資源。

  執行WeditRes,輸入標頭檔案的路徑後選擇“Objects”選單的“New dialog”項,
這時WeditRes會顯示一個對話方塊,標題欄為“Dialog box parameters”,改變對話方塊
的標題為“About this application”或者隨便其它的什麼東西,然後在“Identity”
(識別符號)項鍵入一個你喜歡的東西,比如:“DLG_ABOUT”,在“standard buttons”
選單中選擇“Validate”選項並點選“OK”關閉對話方塊。

  你在這個時候應該可以看到一個新的對話方塊和一個浮動的工具條,在對話方塊中也應
該有一個按紐,你可以用滑鼠拖動它來重新指定它的位置,如果你還想改變按紐上顯示
的文字——雙擊它開啟屬性對話方塊,或者先選定它,然後在浮動工具條下改變顯示文字。

  下面我們新增一個靜態文字標籤,在工具條上選擇文字工具,游標形狀變成由一個
矩形包圍的指標,在對話方塊的窗體上點選一下,一個包含文字——“Text”——的矩形
會出現在你點選的地方,可以通過滑鼠拖動來改變這個文字框的大小,同樣也可以改變
顯示的文字和文字框的位置。
  我們還可以在這個對話方塊中新增其它的裝置。空心方框、實心方框和元件盒等可以
對這個對話方塊進行一些簡單的裝飾。如果你想要刪除一個裝置,選定它然後按
[Ctrl] + [X],或者選擇“Edit”選單的“Cut”項。還可以選擇“Options”選單的
“Test”項測試這個對話方塊的外觀。在工具欄裡有一個按紐的功能是相同的,就是看起
來象一個開關的那個,如果想要繼續編輯這個對話方塊,只要再次選擇上述選項一次即可。

  編輯完成後在“File”選單中選擇存檔,然後關閉WeditRes,為了顯示這個對話方塊
下面我們必須在程式中包含相應的程式碼。

  尋找“OnCommand”語句,在那裡肯定有一個switch語句的條件之一是選單命令
“Exit”的(IDM_EXIT),現在我們為我們的新對話方塊新增一個新的case條件,輸入如
下程式碼:

case IDM_ABOUT:
  DialogBox (hInst, MAKEINTRESOURCE(DGL_ABOUT), hwnd, AboutDlgProc);
  break;

  我們還需要編寫對話方塊函式。

BOOL CALLBACK AboutDlgProc (HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam)
{
switch (msg)
{
  case WM_COMMAND:
    if (LOWORD(wParam) == IDOK)
    {
    EndDialog(hwnd,0);
    return TRUE;
    }
    break;
}
return FALSE;
}

  你應該已經明白了,由嚮導來生成程式碼要簡單得多!現在編譯、連結這個程式,然
後執行它,選擇“Compiler”中的“Execute prj.exe”項,我們建立的對話方塊將顯示
在螢幕上了。

新增其它型別的資源
 你還需要知道如何新增其它資源,如圖示等。

  事實上WeditRes還不能編輯圖示檔案,作者說正在做這方面的工作。所以你可能要
使用其它的工具來完成圖示編輯的工作。

  在資源建立完後,你要把它新增到工程的資源描述檔案裡面去。如果你是使用嚮導
建立的工程。你只須要開啟與工程名相同的*.RC檔案就可以了。

  如果你沒有使用嚮導,那麼你只能新建立一個RC檔案。如果你是使用WeditRes建立
的資源,在建立資源描述檔案時有些事情是你必須知道的——必須包含WeditRes資源,
甚至於你並沒有使用任何由WeditRes建立的資源,你完全有可能在後續的工作中用到,
我建議無論什麼情況都應該象下面這樣做。

  WeditRes一般要建立三個檔案:一個*.DLG檔案、一個*.H標頭檔案和一個*.RES二進
制資原始檔。DLG檔案描述了由WeditRes建立的資源的定義(如:資源串、選單和對話
框等),H檔案是所有資源的符號名的定義,RES檔案是編譯後的二進位制資原始檔,這個
檔案將被連結到工程最後生成的可執行程式中。

  資源描述檔案(*.RC)的檔名一定要和RES檔案的檔名相同,當Lcc-Win32的資
源編譯器(lrc.exe)編譯資源時將覆蓋原來的RES檔案。你可以在Wedit中建立資源描
述檔案,如下:

#include <windows.h>
#include "resources.h"
#include "resources.dlg"

息。

  第二行包含由WeditRes產生的資源的符號名的標頭檔案,我在這裡假定你的資源工程
名為“resurces”,可以改為你所定義的名稱。第三行是WeditRes產生的資源描述檔案,
這樣不會丟失你已經建立了的資源。

  下面你可以向資源描述檔案中增加資源,下面是一個例子:

IDI_MYICON ICON myiconfile.ico

  這一行定義了圖示資源,在使用前,一定要定義圖示的符號名。比如在“prjwiz.h”
檔案(或者“resource.h”,如果你沒有使用嚮導)中,如果你沒有定義這個符號名,
那麼編譯器將認為它是一個字串名。

  新增游標或者點陣圖資源的步驟是相同的,只要把關鍵字改為“BITMAP”或者
“CURSOR”。

  下面要做的是把資源描述檔案包含在工程檔案列表中,當下一次你編譯工程,資源
編譯器也將編譯這個資源描述檔案,並把產生的二進位制資源連結到執行檔案內。


  這樣你可以新增圖示、游標和點陣圖資源,對於其它型別的資源可以使用RCDATA資源
方式新增到資原始檔內,就是一系列的由逗號分隔的數值資訊,這種方式可以使Lcc-Win32
的資源編譯器不支援的資源得以新增到資原始檔中去,比如WAV檔案等。

使用非規格資源
  Lcc-win32的資源編譯器可以使用各種型別的資源,如對話方塊、選單、圖示等,但
是它不能使用其它非規格的資源如多媒體檔案(WAV,MID等等)。

  你可能認為使用其它的資源編譯器如微軟在Win32 SDK中提供的資源編譯器,或者
其它的什麼東西。

  但是這裡的麻煩事是LCCLINK,因為它並不認識這些資源,因此也不可能把這些資
源連結到你的執行檔案中去,這和真是個大問題,你可能不得不使用其它的連結器,這
意味著可能需要其它類性的入口庫。

  我認為這樣做不是一個好的解決方案,主要的原因是Wedit不是設計成可以使用其
它的連結器的,你將不得不在命令列下編譯你的程式,放棄了Lcc-Win32 IDE提供的全
部優點。

  但是這裡還是有一個可供選擇的方案,——幸運的是LRC支援RCDATA資源型別,這
種資源型別用來包含二進位制資料型別的資源,使用一系列的數字列表表示。
 下面是具體的實現方法:

  首先你需要轉換你要使用的二進位制檔案到有一系列的有逗號分割數值表示的文字文
件,LRC預設的認為這些資料是16位長的,它同時也支援32位長度的整數,只要在數值
後新增“L”字元就可以了。

  你可以從這裡下栽做這些工作的轉換器:

  * Bin2Txt: 開發者:Josef Planeta. 十分的靈活方便;
  * TextIt: 本文作者開發,可以一次轉換多個檔案。

  這兩個工具都帶有原始碼,使用Lcc-Win32開發。

  然後一定要在資源資料中包含這些整數列表,如果你的資原始檔沒有使用資源描述
檔案,如果你沒有使用嚮導生成工程,這是有很大可能的。你一定要建立一個資源描述
檔案,一般是這個樣子的:
#include <windows.h> //basic Windows header file
#include "resources.h" //resource identifiers (generated by WeditRes)
#include "resources.dlg" //resource scripts (generated by WeditRes)

MySound RCDATA
BEGIN
#include "mysound.txt"
END

  在這個例子中,我們包含了一個叫做“mysound.txt”的檔案,這個檔案是由一個
WAV檔案轉換成的資料檔案。

  要注意當前版本的LRC(V981126)在RCDATA資源的大小上是有限制的,如果任何一
個數據檔案大於70Kb,你有可能得到一個溢位資訊(Overflow in resource data),
在未來的版本中可能會有所改進,但是在目前如果出現了這種情況可能只有使用其它的
資源編譯器了。

  使用RCDATA型別定義資源意味著你不能直接的指定PlaySound來播放這些資源,因
為型別是不同的。

 解決辦法是手工把這些資料讀入記憶體,下面的程式碼說明了在PlaySound時要做的事情:

BOOL PlayRcSound (HINSTANCE hInst, LPCTSTR lpszSndName)
{
HRSRC hr;
HGLOBAL hg;
LPVOID lpSndData;

hr = FindResource (hInst, lpszSndName, RT_RCDATA);
if (hr != NULL)
{
  hg = LoadResource (hInst, hr);
  if (hg != NULL)
  {
    lpSndData = LockResource (hg);
    if (lpSndData != NULL)
    {
    return PlaySound((LPCTSTR)lpSndData, NULL, SND_MEMORY);
    /* We do not need to unlock or unload the resource, */
    /* Windows will take care of this */
    }
  }
}
return FALSE;
}

  如果你的資源在標頭檔案中定義有識別符號,叫做:ID_MYSOUND,那麼呼叫函式的方式
應該是:

PlayRcSound (hInst, MAKEINTRESOURCE(ID_MYSOUND));

  另外,如果你給出了一個字串名,比如:MySound,函式呼叫如下所示:


PlayRcSound (hInst, "MySound");

靜態庫和動態庫
  也許程式設計師就是喜歡比喻以類的修辭的,庫的概念就是一個例子,它是用來儲存可
能在許多的程式中使用的程式碼,或者一部分十分專業的程式碼,只要寫一次就可以了,甚
至是由其他的人為你寫的程式碼,這樣使用這些程式碼而完全不用關心具體的實現細節。

  和其它的Windows編譯器一樣,LCC-Win32也支援兩種庫——動態庫和靜態庫。

  靜態庫包含的程式碼在編譯連結時將被新增在可執行檔案中,它被稱為“靜態”庫是
因為一旦它連結到可執行檔案中,就將不可改變(除非重新編譯整個程式)。

  而動態連結庫不會由編譯器連結到可執行檔案中,而是在執行時由作業系統連結的,
這樣即使你改變了這個庫,也不會使整個可執行程式重新編譯。

  靜態庫的編寫要簡單些,只要建立一個型別為“Static library (lib)”的新工程,
新增你要在這個靜態庫中使用的原始資料——函式、資料等等,編譯後就會得到一個
LIB檔案,這個檔案裡面包括了所有你指定的函式和資料。如果你要使用這些函式或者
資料,在“Configuration”對話方塊中的“Linker”表裡的“Additional libraries”
項中指定靜態庫名稱,通知編譯器把這個靜態庫連結到工程裡去,但是千萬不要忘了把
你的靜態庫放到連結器能夠找到的地方,比如:“/lcc/lib”路徑下。

    動態連結庫就有些麻煩了,你要使用兩個檔案而不是一個檔案:動態庫本身——DLL
檔案和關聯入口庫——LIB檔案。入口庫是給連結器使用的,簡單的說它使用來哄騙
連結器的,同時它也包含了使Windows正確的呼叫相應動態庫中的函式的資訊。

  而且,動態庫的功能可以更加的強大,它有一個LibMain()函式,在程式每一次
呼叫它時都要通過它來進行初始化的工作。

  要建立一個動態連結庫,你要建立一個DLL工程,然後你可以使用嚮導生成LibMain()
函式。新增你要使用的函式和資料,在編譯這個工程後,你就可以得到DLL庫和介面庫
檔案。

  如果要使用動態連結庫,象使用靜態庫一樣,要將介面庫放在“/lcc/lib”路徑下,
在“Options”對話方塊中新增這個介面庫。同時也要把DLL檔案放置在Windows能夠搜尋
到的路徑下,Windows搜尋動態連結庫的預設目錄是“/windows/system/”和應用程式
的起始目錄,將動態連結庫放置在這兩個目錄下都是可以的。