2026年5月2日 星期六

自建動態連結程式庫檔案

自建動態連結程式庫檔案


曾慶潭 Ching-Tang Tseng
ilikeforth@gmail.com
Hamilton, New Zealand
2 May 2026


本文係十五年前還用 Win32Forth 系統時所留下的文章,是為了使用 FORTH 系統外部資源時所需要建立之一種觀念的文章記錄。

這是一種有關 FORTH 系統中,叫用微軟作業系統內應用程式界面(API)的觀念問題。這原本不是我喜歡談論的問題,我不喜歡 API ,所以也一直不去碰觸,我個人有能力完全隔離 API ,繼續輕鬆使用任何新出現的 FORTH 系統,對許多人而言,尤其是 FORTH 的新進使用者,則可能不習慣這樣子使用 FORTH 。

API 的出現,確實因大量污染了 FORTH 系統,而影響許多人保持接觸 FORTH 的意願,影響了FORTH 社群的發展,非我所願。有障礙,我們就突破,不如直接研究 API 。

我可以舉一個很簡單的實例,將 API 建進動態連結程式庫(DLL)式的檔案,由 FORTH 系統來自由叫用,讓大家都可以輕鬆的了解,這種使用的技術是如何被引進 FORTH 系統的?此後您就不用再摒棄它,繼而善用它。為此,我才在 60 歲時重新接觸 C 的環境,也只有這樣,才能解決這項別人不願意解決的問題,解決問題的過程,也算得上是一項寶貴的經驗,留下記錄,提供大家參考。

我有能力將實際範例寫得非常簡單易懂,只需四列簡直不像程式的 C 語言程式,而且其中還有兩列只是單個大括弧,就能辦到這樣的事情,但您得仔細的看完本文。這樣的教材,期望能夠告訴大家,精簡的傳遞我們專精的 FORTH 技術是很重要的,如果您是 C 式程式語言專家,也請不要輕視像這樣的 C 程式,它足以解釋許多人搞不清楚的問題,我相信任何人只要肯做,絕對能做得比我還好,我指的是要比四列還少,長篇 C 程式會讓 FORTH 的使用者看不懂,我實在是忍不住了才這樣做的,中國人避免用複雜問題欺侮中國人,四列就夠了。

開始研究問題時,上網瀏覽相關資料是免不了的事情,但很難找出一篇純粹以 FORTH 立場來實現這項技術的精簡文章,也就是說,還沒有這方面正式的相關 FORTH 教材,可以直接翻譯來供給大家參考使用。

我在完成解說問題前,習慣於自己先行實現論述的內容,網路上可以找出無數不在乎 FORTH 而偏重於 C 方面的資料,講述如何在 C 環境中建 DLL ,例如:您就由 Google 鍵入『building and using DLLs』,有數不清的文章可以免費閱讀,我看了上百篇,這些東西不像 FORTH ,是完全不透通的資料,您不能過問或自己追查資料內所敘述的操作步驟,生產 C 編譯器的公司發行產品時,資料內寫了使用者該這樣做,您就只好照著做,否則得不到該系統告訴您的結果,可是得到的結果卻不能用。我使用 FORTH 幾十年,從來沒受過這種氣,非常委屈,為了完成本文,我忍下來了,也希望非得用 C 來解決問題不可的電腦程式用法,這是最後一次。

網上資料通常使用了很大且空洞的篇幅,與花俏又多色的畫面來美化成品,當我記不住一大堆指定操作命令或參數用名時,想將關鍵對象摘錄下來,也出現了許多麻煩,要浪費時間去掉那些沒價值的東西,然後才能以比較節省成本的方式,將重要資料印出來仔細研究,避免浪費紙張、墨水,凡事我都講求節省,我只重內容而不重外表,因此,不會浪費紙張來印出視窗畫面。

想寫本文之前,心中早已具有在 FORTH 環境中如何使用 DLL 內之 API 的觀念,只是不曾依樣自建一個來試一試。這一次這樣做,當然不可能一次就能成功,而且每次在純 C 環境中試出一個成品後,滿懷自信的相信『 C 號稱其轉置能力比別種程式語言強』之說法,立刻就將結果轉進 FORTH 試用,但送進 FORTH 就是不能實現,結果不但不成,問題一耗就是三天不能前進。起先,我以為自己多年不接觸新進電腦系統,沒搞清楚一些奇怪的電腦術語,誤解了說明資料的意思,特地在參加本地 WLUG 組織 Linux 例行活動時,請教這裡的專家,是不是我誤解了術語?做了錯誤的『死性』操作。結果不但是無功而返,反而是我得大費口舌,必須對 Linux 專家講解 C 中的編譯程序概念,當然這些概念也不是我發明的,全是由其他相關資料讀來的,卻對我想解決的問題毫無幫助, Linux 專家大部份也對這些『死程序』一知半解,規定性的說明資料實在太多了,只講英文的電腦專家也看不懂那些英文,但那些英文沒有字典上查不到的單字。

我人在紐西蘭,能直接來往的環境中,現在已經沒有會講中文,還具備電腦技術與共同興趣的朋友,網路上呼叫台灣的朋友,實際上也沒那麼方便,鑽牛角尖的問題只好靠自己了。但是,我還是相當幸運,我有一個在大學裡主修過電腦科學的女婿,而且他仍在電腦科技的領域工作,只要我將電腦問題解釋清楚,通常他都可以協助我解決關鍵問題。女婿平日上班時要忙他自己的工作,假日裡需要累過幾天工作後的休息,我只好自己先行釐清問題,過濾出非問不可的項目,與女婿約好時間逐項解決,能完成這本文,寫下這些記錄,不得不感謝他的協助,這裡只有他能完全聽懂我向他解釋的 FORTH 觀念,他不用 FORTH ,但能幫助我解決 FORTH 以外的電腦問題。

從 FORTH 環境叫用 DLL 中的 API 技術,不是近幾年的最新技術,自從 DLL 使用資料公告給大眾,以便大家可以用它來發展軟體產品時, FORTH 也就同時建立了這項使用方法,但在 90 年代以前,沒有 DLL 的時代, FORTH 系統中不建這種功能,我們卻早已用過這樣的呼叫,只不過以前稱為作業系統 BIOS 中公用中斷程式 INT xx 的功能呼叫而已。

既然這是一項老技術,大家又不熟悉,要搞清它,最好就從一個 FORTH 系統的發展歷史資料中探討相關的問題,如此便能了解當初系統設計這項功能的來龍去脈。我們需要透過一個目前共同推廣的系統才能進行溝通,以 Win32Forth 系統為主,所以大家最好也應了解這個系統存在的可貴。我在網文中找到系統原始設計者支湯姆(Tom Zimmer)回答大眾的信件,才明確的知道某些動態連結程式送進 FORTH 系統時,跑不通的關鍵問題所在。我有種感覺,無論您學那一門學問,這門學問的發展歷史也該仔細讀一讀,否則就很難了解這門學問的精要,此即一例。另外,我從網文中也讀到了,當年歐洲 FORTH 組織,曾因 Tom Zimmer 公開 Win32Forth 系統,供大家免費使用,而頒給他一份金質獎章,這是我在 FORTH 界從未見過的殊榮,也令我更加尊重 Tom Zimmer 及其 Win32Forth 系統。

除此之外,我根據歷史記錄,仔細回顧所有業經公開之 Win32Forth 的所有版本,才知道只有 Fig 總會網站上提供的最原始 V4.2 版是原作者的創作,此後的所有其他版本,均經其他組織刻意修改過,而主要的修改內容,竟然就是以配上後來新出產的 .DLL 檔案內不同之 API 應用,為主要區別所在。讀者可以回顧 V4.2 原始版本的內容,眾多檔案中只有一個容量 382K 名為 wincon.dll 的檔案為這個系統所用 API 的主要來源,沒有其他的 .DLL 檔案了,後來的版本都加裝了其他的 .DLL 檔案,以便取得其他功能的 API 。

因此,V4.2 版以後的 Win32Forth 系統都很花俏,注重畫面表現,雖也修正了幾項後來發現的錯誤,實質內容並沒有很大的改變,但卻將幾項傳統上很有用的 FORTH 專屬性能,刻意的埋沒掉了,例如:將很有用的蛻變編譯(meta compile)操作,轉換成只選畫面中一個指定字母的『死性』操作,這樣做就讓後來接觸 FORTH 的人,更不容易了解蛻變編譯的概念。發行 V4.2 以後版本的幾個組織,好像有意扼殺 FORTH 的研究發展,希望大家只用他們做給您的系統就算了,這些新版本的性能除了畫面漂亮外沒有特出處。

只有一個組織,比較老實,網頁畫面記錄,直到 2009 年,依然只推行 V4.2 的版本,我完全能體會各個組織的用心,但我不願逐一介紹,或區分這些網站。 Tom Zimmer 個人已經不再在 Win32Forth 系統上下功夫,以後的路子要靠使用者自己走,如何走?也由使用者自己決定。也許了解這些歷史,才有一面鏡子,能夠照亮過去、現在與未來。

當初,我只選擇 Fig 總會提供的標準 V4.2 版本發展 ABC FORTH 是正確的,但我也不排斥別人的成就,我曾誇口,任何具有浮點計算功能的 FORTH 系統,我都有能力為它加裝我所設計、可用 50 年以上的 ABC FORTH 系統。目前號稱最新推出的 Win32Forth 版本是 V6.15 版,我當然也能加裝,為了實現我的信念,我就重新在這個版本上實現了同樣的設計,做完了這件事情,我就知道這個版本的問題在那裡了,所以敢進行上述批評。

不僅如此,我早已在數個 FORTH 系統中完成了 ABC FORTH 系統,但沒有必要繼續釋出,理由有三:
一是我不希望已經公開之 ABC FORTH 系統內的指令,被隨便更改,造成因為指令不標準,而無法使用那份『使用說明』的問題。
二是屢次重新編譯我的原始設計,是一件很容易辦到的事情,這樣做當然也容易造成它的不穩定,因此,我刻意將其固定下來後才公開推出。
三是我堅持暫時只在指定地區使用,一切相關發展便易於掌握,目前按照我的安排與大家的認真配合,應該可以達到這樣的要求。
ABC FORTH 系統架建在 Win32Forth 系統上,這個系統的所有問題,應該也都屬於我該關心的問題, API 是個問題,我就理所當然、義不容辭的應該協助解決,現在讓我們來仔細探討, API 是如何建在 DLL 中供 Win32Forth 使用的?

從網文上可以找到的相關資料,都是站在 C 的立場解釋 DLL 的,那是擅長 C 式程式語言者的做法。我要一反常態,從 FORTH 的立場來解釋這種應用,而且將純粹屬於在 C 環境內,如何叫用 DLL 中 API ?的問題排除掉,完全不予討論,那是只會搞 C 的人,才需要關心的問題,與我們無關。

在 Win32Forth 中,想要叫用一個 .DLL 檔案中的 API 來用時,可以簡單到只需使用兩個簡單現成指令 WINLIBRARY 及 CALL 。

假設,有一個在微軟作業系統中堪用的動態連結性程式,檔案的名稱為 mydll.dll ,而這個檔案內有許多具有指定名稱的『功能性程式』(請注意,並接受這個我所使用的適當專有名詞,如果您將這個術語套到文章中所有使用了 API 的位置,那麼,文章唸起來就通順了,而且,意義也淺顯了),在 C 中的術語稱為函數(function),它們實際上就是大家所謂之可以被外部程式叫來使用的 API 了, Win32Forth 也可以隨意叫來使用。我們再度假設,有一個典型的 API ,它的名稱就叫作 subb ,它的功能是將兩個整數相減後得到差值。就憑這兩個假設,就足以讓我們解釋清楚本文打算論述的主題了。此處『mydll』及『subb』是隨意給的命名。

mydll.dll 檔案一旦被放置在與 Win32Forth 系統同一個資料夾中, Win32Forth 系統執行起來之後,想直接使用這個 API 的操作,就只需要執行下列輸入指令,指令當然也能被設計進程式:

WINLIBRARY mydll.dll
10 3 CALL subb

其中,第一列是用來宣告將 mydll.dll 檔案的所有功能,連接進入 Win32Forth 系統所需使用的宣告式操作指令。而 subb 是檔案中的一個功能程式,亦即 API ,它此後就可以自由的被 Win32Forth 系統,以單一個 CALL 指令,如同上述的方式直接叫用了。這樣的教材只能告訴大家, Win32Forth 中要如何叫用一個API ,對已經存在此 FORTH 系統中,與微軟作業系統相關的原始 API ,確實只用 CALL 指令叫用就夠了,但它只是簡例,全面正式的使用,則另有當其他狀況出現時,必須注意的使用規則。例子舉得太簡單了,用法就不容易記住,但如果我教您如何親自來自製出這麼樣的一個 API 後,您就可以終生記得它的用法了。 接下來,我們不得不碰 C 了,但可以不必學得那麼多,有概念將其實現才是最重要的關鍵。

我剛開始嘗試設計這個教材時,規規矩矩的建立了好幾個標準的 C 程式語言的測試程式,吃過不少苦頭,唸了許多很基本與 C 相關的書籍,還做 60 歲自修老學生的筆記,記下 C 標準程式中有那些東西,例如:前處理指引、標準庫存程式、簡化程式中變數名稱之宣告方式、程式主體、程式敘述集合、庫存程式指令……等等等,一大堆術語,然後糊里糊塗的在 Linux 系統跑通了幾十個程式,到現在還是糊里糊塗的使用C系統,只會用系統來產生 .DLL 的檔案,但不會純用 C 自己設計一個能產生 .DLL 檔案的編譯器(Compiler)。

請不要笑我的學習經驗記錄怎麼這麼幼稚? BORLAND 公司才能設計出 TURBO C 之 compiler 的,我是何德何能啊?才玩幾天 C ,就想自己設計 compiler!直到現在,大約它外部 90% 的系統操作命令我都還不會用呢。可是,憑良心講,如果我已經在 FORTH 系統中下了同樣時間的功夫,我應該可以設計出迎合這種需要的一個簡單編譯器了,所以我是不是太小看 C 的 compiler 了?我不堅持我的答案應該是『是』或『否』,但一切事在人為。單純的用 FORTH 寫出能編譯出 .DLL 檔案的一個編譯器,不是大話也不是笑話, FORTH Inc. 發行的 swift FORTH 早就已經能夠辦到了,這個系統可以用 FORTH 直接設計出 .DLL 的檔案,十幾年前就見過它的廣告詞,幾萬元台幣才能買一套,所以大家都不知道,我也沒用過。學會能產生 .DLL 檔案的編譯器,對我而言並不困難,因為我熟悉 FORTH ,能讀通 swift FORTH 的程式,所以不是笑話。我雖對 C 只是一知半解,但已經敢寫這篇文章,教大家 FORTH 需要的部份了,這個教材裡面,一點都不需要涉及將指標指來指去,在 C 中耍帥的技術。

剛開始寫成的幾個程式,都還有 C 的規矩,等到我搞通問題,將結果送進 FORTH 系統,實際執行成功後,我就花時間搞調皮處理,目的就是想寫出本文,教大家一個簡單到不能再簡單之程度的範例,讓大家終生記得。

我的程式只有下列四列:

int subb(int x, int y)
{
return y – x ;
}

就這樣,沒了。這就是我全部的源程式教材,是不是很可笑?可是,它通過了編譯,編譯過程中沒有出現任何的錯誤訊息(Error message),程式被製成 14.7K 份量的 .dll 式檔案,送進了 Win32Forth 系統,實現了前述兩列直接執行的 WINLIBRARY 及 CALL 指令要求,我得到了正確答案 7。

從上列程式看起來,好像我很不會寫程式,不適合當程式設計師。我承認我的程式很不漂亮,很不規矩,很不標準,很不像樣,簡直就在亂搞,不像是程式。可是,都執行出了我自己想要的結果。這些程式跟高手的作品比較起來,我確實只能算是一個調皮的程式實踐者。這些東西我都沒有打算要賣錢,搞得那麼漂亮幹什麼?為了解決問題我才設計程式,不是嗎?只要能解決問題,我為什麼一定要守那些不必要的規矩?所以四列就是四列,不必多列。

接下來,我們要探討上述教材,能夠被執行出實質結果的一些關鍵問題,這一部份全都是重要觀念,文章可不是信手拈來隨便寫成的,得到確切的結論前,當然也必須實現遠多於需要的研究與測試。

四列 C 例程式, API 的名稱為 subb ,按 C 規矩來解釋:

執行 subb 前,系統堆疊上要先準備好兩個整數,一個是 int x ,另一個是 int y ,它們被包括在小括弧中,注意 x 與 y 被宣告的次序, x 在先, y 在後。 subb 功能程式的執行內容,就是被包括在兩個大括弧之間的程式敘述,此例被刻意簡化成只做一件事,就是將 y-x 計算後的整數結果回傳給系統,而且就將其放置在堆疊上。由於整個功能程式 subb 執行後的結果,回傳給系統的資料型態(Data type)為一個整數,因此,在 subb 的名稱前面,需要使用 int 前引。沒了,這就是全部 C 程式的詳細解釋。

我在 ABC FORTH 系統中,設計了屬於 BASIC 式程式的大括弧指令,也做了跟這裡大括弧之意義完全一樣的功能設計,但當初設計 ABC FORTH 前,從未探討過 C 中大括弧的真正意義。從這裡看起來, C 中大括弧的意義,跟我為 BASIC 設計的大括弧意義,完全一樣。換句話說,我個人就有能力設計出一些 C 的編譯程式,但我可以把編譯環境設計得比 C 更人性、更友善。

回到 Win32Forth 的環境,我們實現這份教材時使用了『10 3 CALL subb』一列參數與指令,系統執行時, 10 比 3 先進堆疊,傳到了 C 環境後, 3 卻先傳給x , 10 才隨後傳給 y ,但兩個數字都沒有消耗掉,仍然保留在 FORTH 系統的堆疊上,執行完 y-x 後得到了 7 ,這個數字再度被擠進 FORTH 的堆疊,才結束程式。所以, FORTH 系統執行完這一列程式後,堆疊上有 3 個數字: 10、3、7 ,這就是全部外顯的執行結果。

我設計的教材,指令執行前,需要兩個整數,而且故意用減法,兩種系統,在堆疊參數的傳遞上,誰先?誰後?的不同效果,才能顯現出來。程式雖簡單,卻代表了一切,兩個大括弧間的程式敘述內容想寫進多少?那是專搞 C 的人才需要傷腦筋的事情,與 FORTH 無關,所以您不必學,我也不必教。想設計出許多個不同的功能程式,全部放在同一個 mydll.dll 程式中備用,依上例增建與 subb 功能程式同樣的結構,就能辦到,這也不是我該教的問題。您有沒有想過?用這種方法可以全用 C 程式提供 FORTH 系統檔案界面功能、浮點計算功能、繪圖界面功能……等等,這也不是我想教的課題。全力以赴,都能辦到,但界面並不單純,例如:浮點數算完了還是得顯示出來,就又非用 FORTH 不可了,所以沒有人用 C 這樣子為 FORTH 系統設計程式。

至於 FORTH 與 C 兩個系統間的參數傳遞格式,我們只需就 FORTH 這方面提示一下就夠了。浮點數也能傳遞,但您要先搞清楚格式,兩者必須相同。如果傳遞的是記憶體位址,那麼,在 C 環境中使用的是絕對位址,在 Win32Forth 系統中使用的是相對位址,二者可執行 rel>abs 或 abs>rel 指令來換算。如果傳遞的是字串時,在 Win32Forth 系統中使用特殊的『z”………”』指令,來進行包裹。由於這種技術並非標準用法,而且我也不認為再過多少年後,這種使用技術還能永遠存在,所以這些說明,只宜作為應景教材。

※以下係關於 C 系統方面的操作細節,與 FORTH 無關。

使用 C 的系統來產生我們所需要的 .DLL 檔案,方法不是固定的只有一種,因為就 C 的立場而言,全世界所有供應 C 系統的公司,也未將此事統一起來。曾經較為流行的 C++ 或 C# ,所安排出來的作法,是在源程式緊接著前處理指引宣告之後,增加一列額外的宣告:

extern “C” {………………}

然後在功能程式(Function)的前引,再增加另一個宣告指令,例如:

_declspec(dllexpot) FUNCTION-NAME() {………………}

如此設計程式, C 系統才能編譯出您想要的 .DLL 程式來。也許其他的 C 系統還有其他的設計格式,但都只能從研讀發行 C 系統公司所提供的使用說明書中,才能得知詳細的使用方法,沒用到前沒有先行學習的價值。

這樣的用法,有一個很大的缺點,想造 .DLL 程式的人,必須取得 C 的源程式,然後明確的按照要求,如同上述的方式,在源程式的相關位置,填入上述宣告或指令。必須有源程式,還必須修改,系統程式可能還得花錢買,隨後還得進行特殊的編譯操作,才能得到可用的結果,以這種方式實現自行建造 .DLL 的整套方法,確實不太好。因此,我僅只保留收集所得的相關資料,而不進入那種環境去研究發展。

評估現況之後,覺得使用公益軟體,來了解這項 FORTH 與 C 間的初步性能,可能比較理想,於是先從 Linux 中的 gcc 開始發展, gcc 建 .DLL 的方式有一個很方便的特點,就是完全不用修改基本的 C 源程式內容,而只需在操作 gcc 的編譯過程中,使用指定操作命令按步驟操作,使用者只須集中注意力於編譯操作上。

C 的範例源程式並不難建立,但有經驗的使用者,建議使用只產生素文字的編輯器,設計 C 的源程式,在微軟作業系統中指的是記事本(NotePad)而非文件檔案編輯器(WordPad),以避免文字控制碼夾雜在源程式中,妨礙後續的編譯操作。

此前,我曾使用過此 Linux 系統中的 gcc ,編譯出 gForth 及丁陳老師傳給我的 eForth in C 源程式,所以系統值得信賴。根據收集到的資料顯示,以 gcc 產生 .DLL 檔案,只有兩次的操作,例如:源程式的檔案名稱假設為 mydll.c ,則先用此源程式編譯出一個物件檔案(Object file),操作方式為:

gcc –c mydll.c

操作完成後,可以 ls 操作命令檢查資料夾內的檔案,就會增加了一個名為 mydll.o 的物件檔。接下來,要用這個物件檔,直接產生一個外界可以使用的動態連結檔,也就是我們想要的 .DLL 檔案。操作時要用到一個意義上為外界可以共享(Shared)的操作命令,操作方式為:

gcc –shared -o mydll.dll mydll.o
如此便完成了我們想要的 mydll.dll 共享式庫存程式檔案,這兩個操作程序,算是已經被我濃縮到了最簡單的程度。

隨後,我利用 E-mail 傳送信件時夾帶檔案的方式,發了一封自己傳給自己的信件,再到另外一台電腦上取出此 mydll.dll 檔案,放置在 Win32Forth V4.2 系統的資料夾內,立刻以上述指令直接操作測試,不幸失敗了,失敗現象是一執行到叫用的功能程式時,整個視窗就立刻消失了,因不留痕跡,無法除錯。

檢討問題時,直覺想到也許就是因為作業系統完全不同,所以不能這樣用。於是在網路上下載了一個 cygwin 的系統,它是一個在微軟作業系統中模擬 unix 作業系統的設計,提供相同功能的 gcc ,我在這個系統中重新做了許多次與 Linux 中完全相同的操作,並將結果直接送進 Win32Forth V6.14 測試,仍然失敗了,失敗現象比前一狀況好了一些,視窗沒有消失,畫面上顯示錯誤訊息,告知找不到一個稱為 cygwin1.dll 的相關庫存程式,於是,我從下載的系統 bin 資料夾內複製了這個程式,併同 mydll.dll 一起放進 Win32Forth V6.14系 統的資料夾內,再度進行同樣的操作,仍然失敗,視窗畫面也消失了。

最後,我仔細思考問題所在,並從網路上印出了一篇 Tom Zimmer 於 1997-12-04 寫給 Thomas 的網路論壇公開信,信中強調, Win32Forth 當初設計時,考慮到微軟作業系統提供的動態連結程式庫,佔用了記憶體的固定位址,任何程式不得侵犯,否則就不能在微軟的作業系統中執行,因此, Win32Forth 系統中的程式碼改採以相對位址的方式被執行,速度會慢一點,但此系統便可以被彈性的安排在記憶體的任何位置來執行。信中也提到,凡想被 Win32Forth 系統叫用的 .DLL 程式,被叫用而進入系統時,絕對不可以使用與微軟作業系統衝突的記憶體位置。關鍵性的三句話是:

1. WindowsNT allows an absolute program in the area between 0x400000 and about 0x600000.
windows95 I believe places programs well below this.
So if you are specifying an absolute program address below 0x400000, then it won’t run under WindowsNT.
2. You have to be careful to not allocate the same absolute address to two Dlls.
3. This is basically why I decided to make Win32Forth use relative addressing. It is slower, but more flexible.

因此,我直覺上知道前述的兩個 gcc 都產製了與微軟作業系統衝突的 .DLL 檔案。要解決這個問題,只能找合乎規格的 C 編譯系統來用,因為只是試用,不值得花錢買任何系統,但公益系統必須是藉由微軟的基礎開發出來的系統,才會考慮產生的 .DLL 檔案程式,執行時不與微軟作業系統衝突的問題,我缺乏這方面的概念,只好找女婿幫忙,他很快的從網路上找到了我需要的東西,就是 MinGW 系統,裡面也有 gcc ,但要到 DOS 的原始視窗中去執行,執行的結果可以與 gcc 暫時同放置在 MinGW 的 bin 資料夾內,要使用時,才將 mydll.dll 檔案移到希望放置的資料夾中去。

做好了這樣的安排,一次便完成了希望的測試,得到了很正確的結果,證明了根據 Tom Zimmer 信中所言而思考的方向是對的。有了結果,我便有機會進行精簡範例程式的發展,最後,將寫成這篇教材所需要的範例程式,精簡成了只剩四列。

妥善操作 gcc 所需用到的整體操作命令選項(Overall options),是能夠完成自行產製 .DLL 檔案的最重要關鍵,有關整體操作命令選項的使用資料非常多,而且不容易建立概念,想熟悉它們,最好的方式,還是從網路上參考別人完成的實例,並練習實作後,體會操作結果所表示的意義,才能逐漸的熟悉起來,做這件事,必須在學習 C 程式設計方面下許多功夫,操作這些東西,完全沒有學問,所以我也很不想學。

講完了這些技術,並不表示一切就到此為止,您如果好學,在 FORTH 的領域,完全可以學通這種兩個程式語言間的橋接技術, FORTH 系統是完全透通的,使用 SEE 指令,可以直接追蹤這些指令是如何設計而成的,看懂了程式與系統的意義,您也可以在自己的環境中依樣設計一個,除了 FORTH ,這個世界目前還沒有任何其他程式語言,能夠提供如此健全的功能給使用者。

如果大家都從小就開始學 FORTH 程式語言,會有許多好處,它不僅只是可以供您寫程式解問題而已,它還提供了完全可以學得通的一切與電腦有關之哲理。如果您也像我一樣使用了 FORTH 已經 30 幾年,能夠像我一樣將 FORTH 系統執行的原理寫成文章,那麼,上述文章中大家可能會認為是我在講笑話的事情,就不再會被認為是笑話了。

我可以不去追蹤本文所論述的這項技術所牽扯到的指令,單憑自己的想法,設計出另一套由 FORTH 去叫用其他程式語言功能程式的指令來,問題只在於需不需要一直發展這樣的程式?我總認為別的程式語言最後都會死去,而永遠都可以存在的 FORTH ,只能在別的程式語言還活著的時候,跟它們連一連,等它們都死掉了,連在一起也就沒有任何用處了,到頭來還是只剩下 FORTH 。這幾十年來的日子, FORTH 是怎麼過的?好像是千山它都獨行,請不必相送。

早期的系統駐留功能(Resident 例如:side kick用法),我用幾個指令就能完成設計,只要不搞破壞,讓兩個系統可以串來串去,不也是互相叫用功能程式嗎?我們曾用這樣的方式請 BASIC 幫忙算浮點計算,也讓 FORTH 幫忙 BASIC 執行一些程式,將結果放進 BASIC 固定的參數堆放位置。

我親自設計過好幾次多工程式(Multi tasking),用得漂亮時,只控管一個使用者指標 UP(User Pointer)的技巧,就能讓原 FORTH 系統完全停頓下來,轉執行其他任意的別種功能程式,別的功能程式結束了,仍然只依靠那個被控管的 UP 指標值,再執行很少的低階快速指令,就能恢復整個 FORTH 系統的繼續執行。 使用同樣的技巧,當然也能讓 FORTH 去執行 .DLL 內的功能程式。本文所探討的 FORTH 指令,大部份都在執行功能程式名稱的處理,接受 CALL 的後續輸入字串後,到 .DLL 的檔案內去尋找這個功能程式名稱所在的位置,找到了就取得這個功能程式該有的起始執行位址,合理控管 UP ,就能在執行完功能程式後,恢復 FORTH 系統的原有正常狀況。我也因此能夠體會出為什麼 Win32Forth 系統在執行完 CALL 功能程式之後,從堆疊傳遞過去的參數,依然還擺在原來的堆疊位置,交還給 FORTH 系統。我講得出這樣的執行機制,我為什麼不能自己也設計出這樣的程式來?

進一步誇口,我已經很熟練於操作我自己設計的檔案讀寫程式了,我能看到所有其他檔案程式的內容,我讀得進別人的標準結構,我當然也設計得出別人所需要的結構,因為工作只是填資料。那麼,前述所說的笑話就不是笑話,單用 FORTH 設計一個可以產生.DLL 程式供別人使用的檔案,當然能夠辦到,這就是產生 .DLL 程式編譯器的設計方法,我不是在講笑話吧?我用 C 辦不到,我用 FORTH 絕對辦得到,現今,別人已經辦到了,想做時,也能拿來參考。

而且,早就有商售 FORTH 系統,在網頁上做廣告,強調可以直接叫用 Visual BASIC 編譯產生的程式,我卻不認為這是甚麼偉大的新技術,也不值得投入太多精力去發展,因為, Visual BASIC 也早就開始逐漸地沒落了。叫用其它程式語言編譯出來的程式之技術,最後的處境都將相同,等到發行公司因無利可圖而不再賣這個系統時,前面的努力,都會成為泡影。為了節省非常有限的 FORTH 人力,這種發展就不必重覆浪費了。

目前, C 式語言還在流行階段,熟悉這些同類程式語言的讀者,可以參考本章的內容,依樣畫葫蘆,滿足一下新奇感就夠了,我並不鼓勵長期這樣子發展系統,因為產生的結果,就像 C 式程式語言的本質一樣,系統本身是完全不透通的,對技術的傳承,完全沒有幫助。我也希望,此後永遠不再需要使用 C 來寫程式。