作為 Delphi 的兄弟, C++ Builder 在很多方面都跟 Delphi 是如出一轍,在 SOAP/WebService 方面當然也是大同小異了。關於用 Delphi 進行 SOAP/WebService 應用開發,本站曾經有多篇文章作了介紹,大蝦李維也已經為此出版了一本專著,所以我也就不想再多說了。但因為前幾天在論壇上看到有人在討論李維的書和用 C++ Builder 做 SOAP/WebService 應用的問題,所以我照本站那幾篇介紹 Delphi 做 SOAP/WebService 的文章也寫幾篇 C++ Builder 的文章。 所用平台:Borland C++ Builder 6 + Update1、Windows 2000 Server、IIS5 服務端: 1.New|WebServices|Soap Server Application ,如,與 Delphi 6 + Update 2 相比,除了左上方的表徵圖以外,完全相同: 選 Web App Debugger executeable 類型, CoClass Name 為:wadSoapDemo1 ,如: 確定後將自動提示是否要建立一個介面,如,確定即可開啟建立介面嚮導,如果要以後再增加介面,可以在 New|WebServices 中選擇 SOAP Server Interface 同樣可開啟建立介面嚮導: 2.建立介面嚮導如,輸入介面名:Hello 即可產生一個 SOAP 服務端介面: 如果選中 Generate sample methods 即可在產生的介面中同時產生一系列方法,比較全面地說明了如何在介面中定義方法,利用這個選項,可以很方便地學習 C++ Builder 6 的 SOAP 開發方法。 Service Activation Model 可以指定服務端的啟用方式:Per Request(每次請求服務時啟用)/Global(全域)。預設為 Per Request ,這種方式下,在用戶端的每次服務要求時建立服務,響應結束後也結束服務;對於 Global 方式下,服務端只有一個服務執行個體,所有的用戶端服務要求都由此執行個體處理,具體是通過一個叫 xxxFactory 的全域靜態函數來實現的; 3.SaveAll , Unit1 命名為: MainWM , Project1 命名為: Demo1 , Hello 不改名; 4.在介面單元的標頭檔(Hello.h)中增加一個方法 -- GetHello ,如下: __interface INTERFACE_UUID("{3C8C8426-1CF2-423D-B09E-5FEB5716B3C4}") IHello : public IInvokable { public: virtual AnsiString GetHello( int aID ) = 0; // 新增的方法 }; typedef DelphiInterface _di_IHello;
其中的 __interface 並不是新增的關鍵字(Borland 還不至於敢去擅改 C++ 的標準的^_^),它只是一個宏,其實也就是 class ,只不過更清楚地說明了這是一個介面,所謂介面就是要求用 __interface 定義的類必須是完全抽象類別(所有的成員函數都必須是純虛函數);所以我們新增的方法 GetHello 就是一個純虛函數。 5.實現 GetHello 函數,下面是在介面單元檔案(Hello.cpp)中產生的類定義和我們加入的方法及其實現: class THelloImpl : public TInvokableClass, public IHello { public:
AnsiString GetHello( int aID ); // 這是新增方法的定義
/* IUnknown */ HRESULT STDMETHODCALLTYPE QueryInterface(const GUID& IID, void **Obj) { return GetInterface(IID, Obj) ? S_OK : E_NOINTERFACE; } ULONG STDMETHODCALLTYPE AddRef() { return TInterfacedObject::_AddRef(); } ULONG STDMETHODCALLTYPE Release(){ return TInterfacedObject::_Release(); }
/* Ensures that the class is not abstract */ void checkValid() { delete new THelloImpl(); } };
AnsiString THelloImpl::GetHello( int aID ) { if ( aID == 1 ) return "Hello"; else return "world"; }
正如其中的注釋說明的那樣,在這個類裡還實現了 IUnknown 介面,並且通過一個 checkValid() 函數來保證這個類實現了介面中定義的所有純虛函數。其中的 GetHello 就是我們新增的介面方法,包括它的一個非常簡單的實現。 6.下面這段自動產生的程式碼是用於註冊介面及其實作類別的,因為 C++ 中沒有像 Delphi 那樣的 Initialization ,所以用的是編譯指令 #pragma startup 來實現: static void RegTypes() { InvRegistry()->RegisterInterface(__interfaceTypeinfo(IHello)); InvRegistry()->RegisterInvokableClass(__classid(THelloImpl)); } #pragma startup RegTypes 32
7.編譯之即可產生: Demo1.exe ; 先運行一次 Demo1.exe ,完成註冊的工作後啟動 Web App Debugger 。開啟瀏覽器, 輸入 URL 為: http://localhost:1024/Demo1.wadSoapDemo1 即可看到一個標準的 SOAP 應用說明頁面,點擊進入相應連結即可看到相關的 WSDL 。 用戶端程式: 1.New|Application 建立一個一般 VCL 應用程式; 2.SaveAll , Unit1 命名為 ClnMain , Project1 命名為 Client ; 3.New|Web Services|Web Services Importer : 在中的URL中輸入: http://localhost:1024/Demo1.wadSoapDemo1/wsdl/IHello, 如果上面用瀏覽器可以看到正確的 XML 文檔的話,選擇“Next”後將產生匯入的結果,如: 其中有我們在服務端定義的介面 IHello 及其方法 GetHello ,選擇完成即可產生介面單元; 4.SaveAll, IHello 單元不改名儲存,再在 ClnMain 中 #include IHello.h ; 5.在 Form 上放上一個 LabeledEdit 和一個 Button 兩個控制項即可,如: 6.雙擊 Button1 輸入下面的程式: void __fastcall TForm2::Button1Click(TObject *Sender) { LabeledEdit1->EditLabel->Caption = GetIHello()->GetHello( StrToInt( LabeledEdit1->Text ) ); }
7.編譯運行,在 Edit 中輸入"1"按 Button1 , Label 中將顯示"Hello",輸入其它數字將顯示"world"; 就這樣,完成了一個用 C++ Builder 實現的 SOAP 應用,是不是跟 Delphi 沒什麼不同? [Mental Studio]猛禽 Apr.30-02 |