A. EDI 的系統組成是什麼
EDI系統由EDI技術標准、EDI軟體及硬體、EDI技術通信網路3個要素組成。EDI裝置由增壓泵、電去離子(EDI)膜塊、直流穩壓電源、流量計、儀表等組成。
EDI系統是利用混合離子交換樹脂吸附給水中的陰、陽離子,同時被吸附的離子又在直流電壓的作用下,分別透過陰、陽離子交換膜而被去除的過程。電滲析器的一對電極之間,通常由陰膜,將一定數量的EDI單元間用網狀網隔開,構成濃室和淡室。
淡室水中陽離子向負極遷移透過陽膜,被濃室中的陰膜截留,水中陰離子向正極方向遷移陰膜,被濃室中的陽膜截留,淡水又在單元組兩端設置陰/陽離子分別穿過陰、陽離子交換膜進入濃水室而被去除。而通過濃水室的水將離子帶出系統,成為濃水。從而達到淡化、提純、濃縮或精製的目的。
(1)在edi軟體結構中擴展閱讀
EDI膜堆是EDI工作的核心,膜堆是由陰、陽離子交換膜,淡、濃水室隔板,離子交換樹脂和正負電極等按一定規則排列組合並夾緊所構成的單元。膜堆中淡 水室相當於一個混床,使用的離子交換樹脂是磺酸型陽樹脂和季胺型陰樹脂,淡水室中的樹脂必須裝填緊密。
EDI膜堆系統在每個單元內都有兩類不同的室,待除鹽的淡水室和收集所除去雜質離子的濃水室。淡水室中用混勻的陰、陽離子交換樹脂填滿,這些樹脂位於兩個膜之間,只允許陽離子透過的陽離子交換膜及只允許陰離子透過的陰離子交換膜。
B. EDI的軟體結構中包含哪些模塊
用戶介面模塊
內部介面模塊
報文生成及處理模塊
該模塊有兩個功能:
a.接受來自用戶介面模塊和內部介面模塊的命令和信息,按照EDI標准生成訂單、發票等各種EDI報文和單證,經格式轉換模塊處理之後,由通信模塊經EDI網路發給其它EDI用戶。
b.自動處理由其它EDI系統發來的報文。在處理過程中要與本單位信息系統相聯,獲取必要信息並給其它EDI系統答復,同時將有關信息送給本單位其它信息系統。
如因特殊情況不能滿足對方的要求,經雙方EDI系統多次交涉後不能妥善解決的,則把這一類事件提交用戶介面模塊,由人工干預決策。
格式轉換模塊
所有的EDI單證都必須轉換成標準的交換格式,轉換過程包括語法上的壓縮、嵌套、代碼的替換以及必要的EDI語法控制字元。在格式轉換過程中要進行語法檢查,對於語法出錯的EDI報文應拒收並通知對方重發。
通信模塊
該模塊是EDI系統與EDI通信網路的介面。包括執行呼叫、自動重發、合法性和完整性檢查、出錯報警、自動應答、通信記錄、報文拼裝和拆卸等功能。
除以上這些基本模塊外,EDI系統還必須具備一些基本功能。
a.命名和定址功能
EDI的終端用戶在共享的名字當中必須是唯一可標識的。命名和定址功能包括通信和鑒別兩個方面。
在通信方面,EDI是利用地址而不是名字進行通信的。因而要提供按名字定址的方法,這種方法應建立在開放系統目錄服務ISO9594(對應ITU-T X.500)基礎上。在鑒別方面,有若干級必要的鑒別,即通信實體鑒別,發送者與接收者之間的相互鑒別等。
b.安全功能
EDI的安全功能應包含在上述所有模塊中。它包括以下一些內容:
終端用戶以及所有EDI參與方之間的相互驗證;
數據完整性;
EDI參與方之間的電子(數字)簽名;
否定EDI操作活動的可能性;
密鑰管理。
c.語義數據管理功能
完整語義單元(CSU)是由多個信息單元(IU)組成的。其CSU和IU的管理服務功能包括:
IU應該是可標識和可區分的;
IU必須支持可靠的全局參考;
應能夠存取指明IU屬性的內容,如語法、結構語義、字元集和編碼等;
應能夠跟蹤和對IU定位;
對終端用戶提供方便和始終如一的訪問方式。
EDI的操作過程
當今世界通用的EDI通信網路,是建立在MHS數據通信平台上的信箱系統,其通信機制是信箱間信息的存儲和轉發。具體實現方法是在數據通信網上加掛大容量信息處理計算機,在計算機上建立信箱系統,通信雙方需申請各自的信箱,其通信過程就是把文件傳到對方的信箱中。文件交換由計算機自動完成,在發送文件時,用戶只需進入自己的信箱系統。
EDI可以看做是MHS通信子平台,圖2.2、圖2.3、圖2. 4分別表示了EDI在計算機通信網路七層協議中的地位和作用、EDI信箱系統通信和交換原理、以及完整的通信流程。
通信流程中各功能模塊說明如下:
映射(Mapping)—生成EDI平面文件
EDI平面文件(Flat File)是通過應用系統將用戶的應用文件(如:單證、票據)或資料庫中的數據,映射成的一種標準的中間文件。這一過程稱為映射(Mapping)。
平面文件是用戶通過應用系統直接編輯、修改和操作的單證和票據文件,它可直接閱讀、顯示和列印輸出。
翻譯(Translation)—生成EDI標准格式文件
其功能是將平面文件通過翻譯軟體(Translation Software)生成EDI標准格式文件。
EDI標准格式文件,就是所謂的EDI電子單證,或稱電子票據。它是EDI用戶之間進行貿易和業務往來的依據。EDI標准格式文件是一種只有計算機才能閱讀的ASCII文件。它是按照EDI數據交換標准(即EDI標准)的要求,將單證文件(平面文件)中的目錄項,加上特定的分割符、控制符和其它信息,生成的一種包括控制符、代碼和單證信息在內的ASCII碼文件。
通信
這一步由計算機通信軟體完成。用戶通過通信網路,接入EDI信箱系統,將EDI電子單證投遞到對方的信箱中。
EDI信箱系統則自動完成投遞和轉接,並按照X.400(或X.435)通信協議的要求,為電子單證加上信封、信頭、信尾、投送地址、安全要求及其它輔助信息。
EDI文件的接收和處理
接收和處理過程是發送過程的逆過程。首先需要接收用戶通過通信網路接入EDI信箱系統,打開自己的信箱,將來函接收到自己的計算機中,經格式校驗、翻譯、映射還原成應用文件。最後對應用文件進行編輯、處理和回復。
在實際操作過程中,EDI系統為用戶提供的EDI應用軟體包,包括了應用系統、映射、翻譯、格式校驗和通信連接等全部功能。其處理過程,用戶可看作是一個「黑匣子」,完全不必關心裏面具體的過程。
圖2.5是一家貿易公司用EDI通信網路實現報關的工作流程示意圖。
EDI的通信服務
EDI的通信環境(EDIME)由一個EDI通信系統(EDIMS)和多個EDI用戶(EDIMG)組成,見圖2.6。EDI的開發、應用就是通過計算機通信網路實現的,它主要有以下三種方式。
點對點(PTP)方式
點對點方式即EDI按照約定的格式,通過通信網路進行信息的傳遞和終端處理,完成相互的業務交往。早期的EDI通信一般都採用此方式,但它有許多缺點,如當EDI用戶的貿易夥伴不再是幾個而是幾十個甚至幾百個時,這種方式很費時間,需要許多重復發送。同時這種通信方式是同步的,不適於跨國家、跨行業之間的應用。
近年來,隨著技術進步,這種點對點的方式在某些領域中仍舊有用,但會有所改進。新方法採用的是遠程非集中化控制的對等結構,利用基於終端開放型網路系統的遠程信息業務終端,用特定的應用程序將數據轉換成EDI報文,實現國際間的EDI報文互通。
增值網(VAN)方式
它是那些增值數據業務(VADS)公司,利用已有的計算機與通信網路設備,除完成一般的通信任務外,增加EDI的服務功能。VADS公司提供給EDI用戶的服務主要是租用信箱及協議轉換,後者對用戶是透明的。信箱的引入,實現了EDI通信的非同步性,提高了效率,降低了通信費用。另外,EDI報文在VADS公司自已的系統(即VAN中)中傳遞也是非同步的,即存儲轉發的。
VAN方式盡管有許多優點,但因為各增值網的EDI服務功能不盡相同,VAN系統並不能互通,從而限制了跨地區、跨行業的全球性應用。同時,此方法還有一個致命的缺點,即VAN只實現了計算機網路的下層,相當於OSI參考模型的下三層。而EDI通信往往發生在各種計算機的應用進程之間,這就決定了EDI應用進程與VAN的聯系相當鬆散,效率很低。
MHS方式
信息處理系統MHS是ISO和ITU-T聯合提出的有關國際間電子郵件服務系統的功能模型。它是建立OSI開放系統的網路平台上,適應多樣化的信息類型,並通過網路連接,具有快速、准確、安全、可靠等特點。它是以存儲轉發為基礎的、非實時的電子通信系統,非常適合作為EDI的傳輸系統。MHS為EDI創造一個完善的應用軟體平台,減少了EDI設計開發上的技術難度和工作量。ITU-T X.435/F.435規定了EDI信息處理系統和通信服務,把EDI和MHS作為OSI應用層的正式業務。EDI與MHS互連,可將EDI報文直接放入MHS的電子信箱中,利用MHS的地址功能和文電傳輸服務功能,實現EDI報文的完善傳送。
EDI信息處理系統由信息傳送代理(MTA)、EDI用戶代理(EDI-UA)、EDI信息存儲(EDI-MS)和訪問單元(AU)組成,見圖2.7。MTA完成建立接續、存儲/轉發,由多個MTA組成MTS系統。EDI在MHS中的傳遞過程見圖2.8。
EDI-MS存儲器位於EDI-UA和MTA之間,它如同一個資源共享器或郵箱,幫助EDI-UA發送、投遞、存儲和取出EDI信息。同時EDI-MS把EDI UA接收到的報文變成EDI報文資料庫,並提供對該資料庫的查詢、檢索等功能。為有利於檢索,EDI-MS將報文的信封、信首、信體映射到MS信息實體的不同特徵域,並提供自動轉發及自動回送等服務。
EDI-UA是電子單證系統與傳輸系統之間的介面。它的任務是利用MTS的功能來傳輸電子單證。EDI-UA將它處理的信息對象分作兩種:一種稱為EDI報文(EDIM),另一種稱為EDI回執(EDIN)。前者是傳輸電子單證的,後一種是報告接收結果的。EDI-UA和MTS共同構成了EDI信息系統(EDI-MS),EDI-MS和EDI用戶又一起構成了EDI通信環境(EDIME)。
EDI與MHS結合,大大促進了國際EDI業務的發展。為實現EDI的全球通信,EDI通信系統還使用了X.500系列的目錄系統(DS)。
DS可為全球EDI通信網的補充、用戶的增長等目錄提供增、刪、改功能,以獲得名址網路服務、通信能力列表、號碼查詢等一系列屬性的綜合信息。EDI、MHS和DS的結合,使信息通信有一了個新飛躍,為EDI的發展提供了廣闊的前景。EDI、HS和DS的綜合網路見圖2.9。
C. 可以在多線程 DLL 的介面函數中創建線程嗎
比較大的應用程序都由很多模塊組成,這些模塊分別完成相對獨立的功能,它們彼此協作來完成整個軟體系統的工作。可能存在一些模塊的功能較為通用,在構造其它軟體系統時仍會被使用。在構造軟體系統時,如果將所有模塊的源代碼都靜態編譯到整個應用程序 EXE 文件中,會產生一些問題:一個缺點是增加了應用程序的大小,它會佔用更多的磁碟空間,程序運行時也會消耗較大的內存空間,造成系統資源的浪費;另一個缺點是,在編寫大的 EXE 程序時,在每次修改重建時都必須調整編譯所有源代碼,增加了編譯過程的復雜性,也不利於階段性的單元測試。
Windows 系統平台上提供了一種完全不同的較有效的編程和運行環境,你可以將獨立的程序模塊創建為較小的 DLL (Dynamic Linkable Library) 文件,並可對它們單獨編譯和測試。在運行時,只有當 EXE 程序確實要調用這些 DLL 模塊的情況下,系統才會將它們裝載到內存空間中。這種方式不僅減少了 EXE 文件的大小和對內存空間的需求,而且使這些 DLL 模塊可以同時被多個應用程序使用。Windows 自己就將一些主要的系統功能以 DLL 模塊的形式實現。
一般來說,DLL 是一種磁碟文件,以.dll、.DRV、.FON、.SYS 和許多以 .EXE 為擴展名的系統文件都可以是 DLL。它由全局數據、服務函數和資源組成,在運行時被系統載入到調用進程的虛擬空間中,成為調用進程的一部分。如果與其它 DLL 之間沒有沖突,該文件通常映射到進程虛擬空間的同一地址上。DLL 模塊中包含各種導出函數,用於向外界提供服務。DLL 可以有自己的數據段,但沒有自己的堆棧,使用與調用它的應用程序相同的堆棧模式;一個 DLL 在內存中只有一個實例;DLL 實現了代碼封裝性;DLL 的編制與具體的編程語言及編譯器無關。
在 Win32 環境中,每個進程都復制了自己的讀/寫全局變數。如果想要與其它進程共享內存,必須使用內存映射文件或者聲明一個共享數據段。DLL 模塊需要的堆棧內存都是從運行進程的堆棧中分配出來的。Windows 在載入 DLL 模塊時將進程函數調用與 DLL 文件的導出函數相匹配。Windows 操作系統對 DLL 的操作僅僅是把 DLL 映射到需要它的進程的虛擬地址空間里去。DLL 函數中的代碼所創建的任何對象(包括變數)都歸調用它的線程或進程所有。
調用方式
1、靜態調用方式:由編譯系統完成對 DLL 的載入和應用程序結束時 DLL 卸載的編碼(如還有其它程序使用該 DLL,則 Windows 對 DLL 的應用記錄減1,直到所有相關程序都結束對該 DLL 的使用時才釋放它,簡單實用,但不夠靈活,只能滿足一般要求。
隱式的調用:需要把產生動態連接庫時產生的 .LIB 文件加入到應用程序的工程中,想使用 DLL 中的函數時,只須說明一下。隱式調用不需要調用 LoadLibrary() 和 FreeLibrary()。程序員在建立一個 DLL 文件時,鏈接程序會自動生成一個與之對應的 LIB 導入文件。該文件包含了每一個 DLL 導出函數的符號名和可選的標識號,但是並不含有實際的代碼。LIB 文件作為 DLL 的替代文件被編譯到應用程序項目中。
當程序員通過靜態鏈接方式編譯生成應用程序時,應用程序中的調用函數與 LIB 文件中導出符號相匹配,這些符號或標識號進入到生成的 EXE 文件中。LIB 文件中也包含了對應的 DL L文件名(但不是完全的路徑名),鏈接程序將其存儲在 EXE 文件內部。
當應用程序運行過程中需要載入 DLL 文件時,Windows 根據這些信息發現並載入 DLL,然後通過符號名或標識號實現對 DLL 函數的動態鏈接。所有被應用程序調用的 DLL 文件都會在應用程序 EXE 文件載入時被載入在到內存中。可執行程序鏈接到一個包含 DLL 輸出函數信息的輸入庫文件(.LIB文件)。操作系統在載入使用可執行程序時載入 DLL。可執行程序直接通過函數名調用 DLL 的輸出函數,調用方法和程序內部其 它的函數是一樣的。
2、動態調用方式:是由編程者用 API 函數載入和卸載 DLL 來達到調用 DLL 的目的,使用上較復雜,但能更加有效地使用內存,是編制大型應用程序時的重要方式。
顯式的調用:是指在應用程序中用 LoadLibrary 或 MFC 提供的 AfxLoadLibrary 顯式的將自己所做的動態連接庫調進來,動態連接庫的文件名即是上面兩個函數的參數,再用 GetProcAddress() 獲取想要引入的函數。自此,你就可以象使用如同本應用程序自定義的函數一樣來調用此引入函數了。在應用程序退出之前,應該用 FreeLibrary 或 MFC 提供的 AfxFreeLibrary 釋放動態連接庫。直接調用 Win32 的 LoadLibary 函數,並指定 DLL 的路徑作為參數。LoadLibary 返回 HINSTANCE 參數,應用程序在調用 GetProcAddress 函數時使用這一參數。GetProcAddress 函數將符號名或標識號轉換為 DLL 內部的地址。程序員可以決定 DLL 文件何時載入或不載入,顯式鏈接在運行時決定載入哪個 DLL 文件。使用 DLL 的程序在使用之前必須載入(LoadLibrary)載入DLL從而得到一個DLL模塊的句柄,然後調用 GetProcAddress 函數得到輸出函數的指針,在退出之前必須卸載DLL(FreeLibrary)。
Windows將遵循下面的搜索順序來定位 DLL:
包含EXE文件的目錄
進程的當前工作目錄
Windows系統目錄
Windows目錄
列在 Path 環境變數中的一系列目錄
MFC中的DLL
Non-MFC DLL:指的是不用 MFC 的類庫結構,直接用 C 語言寫的 DLL,其輸出的函數一般用的是標准 C 介面,並能被 非 MFC 或 MFC 編寫的應用程序所調用。
Regular DLL:和下述的 Extension DLLs 一樣,是用 MFC 類庫編寫的。明顯的特點是在源文件里有一個繼承 CWinApp 的類。其又可細分成靜態連接到 MFC 和動態連接到 MFC 上的。
靜態連接到 MFC 的動態連接庫只被 VC 的專業 版和企業版所支持。該類 DLL 應用程序里頭的輸出函數可以被任意 Win32 程序使用,包括使用 MFC 的應用程序。輸入函數有如下形式:
extern "C" EXPORT YourExportedFunction();
如果沒有 extern "C" 修飾,輸出函數僅僅能從 C++ 代碼中調用。
DLL 應用程序從 CWinApp 派生,但沒有消息循環。
動態鏈接到 MFC 的 規則 DLL 應用程序里頭的輸出函數可以被任意 Win32 程序使用,包括使用 MFC 的應用程序。但是,所有從 DLL 輸出的函數應該以如下語句開始:
AFX_MANAGE_STATE(AfxGetStaticMoleState( ))
此語句用來正確地切換 MFC 模塊狀態。
Regular DLL能夠被所有支持 DLL 技術的語言所編寫的應用程序所調用。在這種動態連接庫中,它必須有一個從 CWinApp 繼承下來的類,DLLMain 函數被 MFC 所提供,不用自己顯式的寫出來。
Extension DLL:用來實現從 MFC 所繼承下來的類的重新利用,也就是說,用這種類型的動態連接庫,可以用來輸出一個從 MFC 所繼承下來的類。它輸出的函數僅可以被使用 MFC 且動態鏈接到 MFC 的應用程序使用。可以從 MFC 繼承你所想要的、更適於你自己用的類,並把它提供給你的應用程序。你也可隨意的給你的應用程序提供 MFC 或 MFC 繼承類的對象指針。Extension DLL使用 MFC 的動態連接版本所創建的,並且它只被用 MFC 類庫所編寫的應用程序所調用。Extension DLLs 和 Regular DLLs 不一樣,它沒有從 CWinApp 繼承而來的類的對象,所以,你必須為自己 DLLMain 函數添加初始化代碼和結束代碼。
和規則 DLL 相比,有以下不同:
1、它沒有從 CWinApp 派生的對象;
2、它必須有一個 DLLMain 函數;
3、DLLMain 調用 AfxInitExtensionMole 函數,必須檢查該函數的返回值,如果返回0,DLLMmain 也返回 0;
4、如果它希望輸出 CRuntimeClass 類型的對象或者資源,則需要提供一個初始化函數來創建一個 CDynLinkLibrary 對象。並且,有必要把初始化函數輸出;
5、使用擴展 DLL 的 MFC 應用程序必須有一個從 CWinApp 派生的類,而且,一般在InitInstance 里調用擴展 DLL 的初始化函數。
DLL入口函數
1、每一個 DLL 必須有一個入口點,DLLMain 是一個預設的入口函數。DLLMain 負責初始化和結束工作,每當一個新的進程或者該進程的新的線程訪問 DLL 時,或者訪問 DLL 的每一個進程或者線程不再使用DLL或者結束時,都會調用 DLLMain。但是,使用 TerminateProcess 或 TerminateThread 結束進程或者線程,不會調用 DLLMain。
DLLMain的函數原型:
BOOL APIENTRY DLLMain(HANDLE hMole,DWORD ul_reason_for_call,LPVOID
lpReserved)
{
switch(ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
.......
case DLL_THREAD_ATTACH:
.......
case DLL_THREAD_DETACH:
.......
case DLL_PROCESS_DETACH:
.......
return TRUE;
}
}
參數:
hMoudle:是動態庫被調用時所傳遞來的一個指向自己的句柄(實際上,它是指向_DGROUP段的一個選擇符);
ul_reason_for_call:是一個說明動態庫被調原因的標志。當進程或線程裝入或卸載動態連接庫的時候,操作系統調用入口函數,並說明動態連接庫被調用的原因。它所有的可能值為:
DLL_PROCESS_ATTACH: 進程被調用;
DLL_THREAD_ATTACH: 線程被調用;
DLL_PROCESS_DETACH: 進程被停止;
DLL_THREAD_DETACH: 線程被停止;
lpReserved:是一個被系統所保留的參數;
2、_DLLMainCRTStartup
為了使用 "C" 運行庫 (CRT,C Run time Library) 的 DLL 版本(多線程),一個 DLL 應用程序必須指定 _DLLMainCRTStartup 為入口函數,DLL 的初始化函數必須是 DLLMain。
_DLLMainCRTStartup 完成以下任務:當進程或線程捆綁(Attach) 到 DLL 時為 "C" 運行時的數據 (C Runtime Data) 分配空間和初始化並且構造全局 "C++"對象,當進程或者線程終止使用DLL(Detach) 時,清理 C Runtime Data 並且銷毀全局 "C++" 對象。它還調用 DLLMain 和 RawDLLMain 函數。
RawDLLMain 在 DLL 應用程序動態鏈接到 MFC DLL 時被需要,但它是靜態鏈接到 DLL 應用程序的。在講述狀態管理時解釋其原因。
關於調用約定
動態庫輸出函數的約定有兩種:調用約定和名字修飾約定。
1)調用約定(Calling convention):決定函數參數傳送時入棧和出棧的順序,由調用者還是被調用者把參數彈出棧,以及編譯器用來識別函數名字的修飾約定。
函數調用約定有多種,這里簡單說一下:
1、__stdcall 調用約定相當於16位動態庫中經常使用的 PASCAL 調用約定。在32位的 VC++5.0 中PASCAL 調用約定不再被支持(實際上它已被定義為__stdcall。除了__pascal 外,__fortran 和__syscall也不被支持),取而代之的是 __stdcall 調用約定。兩者實質上是一致的,即函數的參數自右向左通過棧傳遞,被調用的函數在返回前清理傳送參數的內存棧,但不同的是函數名的修飾部分(關於函數名的修飾部分在後面將詳細說明)。
_stdcall 是 Pascal 程序的預設調用方式,通常用於 Win32 API 中,函數採用從右到左的壓棧方式,自己在退出時清空堆棧。VC 將函數編譯後會在函數名前面加上下劃線前綴,在函數名後加上 "@" 和參數的位元組數。
2、C 調用約定(即用__cdecl 關鍵字說明)按從右至左的順序壓參數入棧,由調用者把參數彈出棧。對於傳送參數的內存棧是由調用者來維護的(正因為如此,實現可變參數的函數只能使用該調用約定)。另外,在函數名修飾約定方面也有所不同。
_cdecl 是 C 和 C++ 程序預設的調用方式。每一個調用它的函數都包含清空堆棧的代碼,所以產生的可執行文件大小會比調用 _stdcall 函數的大。函數採用從右到左的壓棧方式。VC 將函數編譯後會在函數名前面加上下劃線前綴。 它是 MFC 預設調用約定。
3、__fastcall 調用約定是 "人" 如其名,它的主要特點就是快,因為它是通過寄存器來傳送參數的(實際上,它用 ECX 和 EDX 傳送前兩個雙字(DWORD)或更小的參數,剩下的參數仍舊自右向左壓棧傳送,被調用的函數在返回前清理傳送參數的內存棧),在函數名修飾約定方面,它和前兩者均不同。
_fastcall方式的函數採用寄存器傳遞參數,VC 將函數編譯後會在函數名前面加上"@"前綴,在函數名後加上"@"和參數的位元組數。
4、thiscall 僅僅應用於 "C++" 成員函數。this 指針存放於 CX 寄存器,參數從右到左壓。thiscall 不是關鍵詞,因此不能被程序員指定。
5、naked call採用 1-4 的調用約定時,如果必要的話,進入函數時編譯器會產生代碼來保存ESI,EDI,EBX,EBP寄存器,退出函數時則產生代碼恢復這些寄存器的內容。
naked call不產生這樣的代碼。naked call不是類型修飾符,故必須和_declspec 共同使用。
關鍵字 __stdcall、__cdecl 和 __fastcall 可以直接加在要輸出的函數前,也可以在編譯環境的 Setting...\C/C++ \Code Generation 項選擇。當加在輸出函數前的關鍵字與編譯環境中的選擇不同時,直接加在輸出函數前的關鍵字有效。它們對應的命令行參數分別為/Gz、/Gd 和 /Gr。預設狀態為/Gd,即__cdecl。
要完全模仿 PASCAL 調用約定首先必須使用 __stdcall 調用約定,至於函數名修飾約定,可以通過其它方法模仿。還有一個值得一提的是 WINAPI 宏,Windows.h 支持該宏,它可以將出函數翻譯成適當的調用約定,在 WIN32 中,它被定義為 __stdcall。使用 WINAPI 宏可以創建自己的 APIs。
2)名字修飾約定
1、修飾名(Decoration name)
"C" 或者 "C++" 函數在內部(編譯和鏈接)通過修飾名識別。修飾名是編譯器在編譯函數定義或者原型時生成的字元串。有些情況下使用函數的修飾名是必要的,如在模塊定義文件里頭指定輸出"C++"重載函數、構造函數、析構函數,又如在匯編代碼里調用"C""或"C++"函數等。
修飾名由函數名、類名、調用約定、返回類型、參數等共同決定。
2、名字修飾約定隨調用約定和編譯種類(C或C++)的不同而變化。函數名修飾約定隨編譯種類和調用約定的不同而不同,下面分別說明。
a、C編譯時函數名修飾約定規則:
__stdcall 調用約定在輸出函數名前加上一個下劃線前綴,後面加上一個"@"符號和其參數的位元組數,格式為 _functionname@number。
__cdecl調用約定僅在輸出函數名前加上一個下劃線前綴,格式為 _functionname。
__fastcall調用約定在輸出函數名前加上一個"@"符號,後面也是一個"@"符號和其參數的位元組數,格式為@functionname@number。
它們均不改變輸出函數名中的字元大小寫,這和PASCAL調用約定不同,PASCAL約定輸出的函數名無任何修飾且全部大寫。
b、C++編譯時函數名修飾約定規則:
__stdcall調用約定:
1、以"?"標識函數名的開始,後跟函數名;
2、函數名後面以"@@YG"標識參數表的開始,後跟參數表;
3、參數表以代號表示:
X——void,
D——char,
E——unsigned char,
F——short,
H——int,
I——unsigned int,
J——long,
K——unsigned long,
M——float,
N——double,
_N——bool,
....
PA——表示指針,後面的代號表明指針類型,如果相同類型的指針連續出現,以"0"代替,一個"0"代表一次重復;
4、參數表的第一項為該函數的返回值類型,其後依次為參數的數據類型,指針標識在其所指數據類型前;
5、參數表後以"@Z"標識整個名字的結束,如果該函數無參數,則以"Z"標識結束。
其格式為"?functionname@@YG*****@Z"或"?functionname@@YG*XZ",
例如
int Test1(char *var1,unsigned long)-----「?Test1@@YGHPADK@Z」
void Test2() -----「?Test2@@YGXXZ」
__cdecl調用約定:
規則同上面的_stdcall調用約定,只是參數表的開始標識由上面的"@@YG"變為"@@YA"。
__fastcall調用約定:
規則同上面的_stdcall調用約定,只是參數表的開始標識由上面的"@@YG"變為"@@YI"。
VC++對函數的省缺聲明是"__cedcl",將只能被C/C++調用。
關於DLL的函數
動態鏈接庫中定義有兩種函數:導出函數(export function)和內部函數(internal function)。導出函數可以被其它模塊調用,內部函數在定義它們的DLL程序內部使用。
輸出函數的方法有以下幾種:
1、傳統的方法
在模塊定義文件的 EXPORT 部分指定要輸入的函數或者變數。語法格式如下:
entryname[=internalname] [@ordinal[NONAME]] [DATA] [PRIVATE]
其中:
entryname 是輸出的函數或者數據被引用的名稱;
internalname 同 entryname;
@ordinal 表示在輸出表中的順序號(index);
NONAME 僅僅在按順序號輸出時被使用(不使用 entryname );
DATA 表示輸出的是數據項,使用 DLL 輸出數據的程序必須聲明該數據項為 _declspec(DLLimport)。
上述各項中,只有 entryname 項是必須的,其他可以省略。
對於"C"函數來說,entryname 可以等同於函數名;但是對 "C++" 函數(成員函數、非成員函數)來說,entryname 是修飾名。可以從 .map 映像文件中得到要輸出函數的修飾名,或者使用DUMPBIN /SYMBOLS 得到,然後把它們寫在 .def 文件的輸出模塊。DUMPBIN 是VC提供的一個工具。
如果要輸出一個 "C++" 類,則把要輸出的數據和成員的修飾名都寫入 .def 模塊定義文件。
2、在命令行輸出
對鏈接程序 LINK 指定 /EXPORT 命令行參數,輸出有關函數。
3、使用 MFC 提供的修飾符號 _declspec(DLLexport)
在要輸出的函數、類、數據的聲明前加上 _declspec(DLLexport) 修飾符表示輸出。__declspec(DLLexport) 在 C 調用約定、C 編譯情況下可以去掉輸出函數名的下劃線前綴。extern "C" 使得在 C++ 中使用 C 編譯方式成為可能。在"C++"下定義"C"函數需要加 extern "C" 關鍵詞。用 extern "C" 來指明該函數使用 C 編譯方式。輸出的 "C" 函數可以從 "C" 代碼里調用。
例如,在一個 C++ 文件中,有如下函數:
extern "C"
其輸出函數名為:Test
MFC提供了一些宏,就有這樣的作用。
AFX_CLASS_IMPORT:__declspec(DLLexport)
AFX_API_IMPORT:__declspec(DLLexport)
AFX_DATA_IMPORT:__declspec(DLLexport)
AFX_CLASS_EXPORT:__declspec(DLLexport)
AFX_API_EXPORT:__declspec(DLLexport)
AFX_DATA_EXPORT:__declspec(DLLexport)
AFX_EXT_CLASS: #ifdef _AFXEXT
AFX_CLASS_EXPORT
#else
AFX_CLASS_IMPORT
AFX_EXT_API:#ifdef _AFXEXT
AFX_API_EXPORT
#else
AFX_API_IMPORT
AFX_EXT_DATA:#ifdef _AFXEXT
AFX_DATA_EXPORT
#else
AFX_DATA_IMPORT
像 AFX_EXT_CLASS 這樣的宏,如果用於 DLL 應用程序的實現中,則表示輸出(因為_AFX_EXT被定義,通常是在編譯器的標識參數中指定該選項 /D_AFX_EXT);如果用於使用DLL的應用程序中,則表示輸入(_AFX_EXT沒有定義)。
要輸出整個的類,對類使用_declspec(_DLLexpot);要輸出類的成員函數,則對該函數使用_declspec(_DLLexport)。如:
class AFX_EXT_CLASS CTextDoc : public CDocument
{
…
}
extern "C" AFX_EXT_API void WINAPI InitMYDLL();
這幾種方法中,最好採用第三種,方便好用;其次是第一種,如果按順序號輸出,調用效率會高些;最次是第二種。
模塊定義文件(.DEF)
模塊定義文件(.DEF)是一個或多個用於描述 DLL 屬性的模塊語句組成的文本文件,每個DEF文件至少必須包含以下模塊定義語句:
第一個語句必須是LIBRARY語句,指出DLL的名字;
EXPORTS 語句列出被導出函數的名字;將要輸出的函數修飾名羅列在 EXPORTS 之下,這個名字必須與定義函數的名字完全一致,如此就得到一個沒有任何修飾的函數名了。
可以使用DESCRIPTION語句描述DLL的用途(此句可選);
";"對一行進行注釋(可選)。 DLL程序和調用其輸出函數的程序的關系
1、DLL與進程、線程之間的關系
DLL模塊被映射到調用它的進程的虛擬地址空間。
DLL使用的內存從調用進程的虛擬地址空間分配,只能被該進程的線程所訪問。
DLL的句柄可以被調用進程使用;調用進程的句柄可以被DLL使用。
DLL使用調用進程的棧。
2、關於共享數據段
DLL定義的全局變數可以被調用進程訪問;DLL可以訪問調用進程的全局數據。使用同一DLL的每一個進程都有自己的DLL全局變數實例。如果多個線程並發訪問同一變數,則需要使用同步機制;對一個DLL的變數,如果希望每個使用DLL的線程都有自己的值,則應該使用線程局部存儲(TLS,Thread Local Strorage)。
在程序里加入預編譯指令,或在開發環境的項目設置里也可以達到設置數據段屬性的目的.必須給這些變數賦初值,否則編譯器會把沒有賦初始值的變數放在一個叫未被初始化的數據段中。
D. EDI 的系統組成是什麼
EDI系統由EDI技術標准、EDI軟體及硬體、EDI技術通信網路3個要素組成。裝置由增壓泵、電去離子(EDI)膜塊、直流穩壓電源、流量計、儀表等組成。
EDI系統是利用混合離子交換樹脂吸附給水中的陰、陽離子,同時被吸附的離子又在直流電壓的作用下,分別透過陰、陽離子交換膜而被去除的過程。電滲析器的一對電極之間,通常由陰膜,將一定數量的EDI單元間用網狀網隔開,構成濃室和淡室。
淡室水中陽離子向負極遷移透過陽膜,被濃室中的陰膜截留,水中陰離子向正極方向遷移陰膜,被濃室中的陽膜截留,淡水又在單元組兩端設置陰/陽離子分別穿過陰、陽離子交換膜進入濃水室而被去除。而通過濃水室的水將離子帶出系統,成為濃水。從而達到淡化、提純、濃縮或精製的目的。
(4)在edi軟體結構中擴展閱讀
EDI膜堆是EDI工作的核心,膜堆是由陰、陽離子交換膜,淡、濃水室隔板,離子交換樹脂和正負電極等按一定規則排列組合並夾緊所構成的單元。膜堆中淡 水室相當於一個混床,使用的離子交換樹脂是磺酸型陽樹脂和季胺型陰樹脂,淡水室中的樹脂必須裝填緊密。
EDI膜堆系統在每個單元內都有兩類不同的室,待除鹽的淡水室和收集所除去雜質離子的濃水室。淡水室中用混勻的陰、陽離子交換樹脂填滿,這些樹脂位於兩個膜之間,只允許陽離子透過的陽離子交換膜及只允許陰離子透過的陰離子交換膜。
E. 電子商務主要學什麼
電子商務源於英文ELECTRONIC
COMMERCE,簡寫為EC。顧名思義,其內容包含兩個方面,一是電子方式,二是商貿活動。
電子商務指的是利用簡單、快捷、低成本的電子通訊方式,買賣雙方不謀面地進行各種商貿活動。
電子商務可以通過多種電子通訊方式來完成。簡單的,比如你通過打電話或發傳真的方式來與客戶進行商貿活動,似乎也可以稱作為電子商務;但是,現在人們所探討的電子商務主要是以EDI(電子數據交換)和INTERNET來完成的。尤其是隨著INTERNET技術的日益成熟,電子商務真正的發展將是建立在INTERNET技術上的。所以也有人把電子商務簡稱為IC(INTERNET
COMMERCE)。
從貿易活動的角度分析,電子商務可以在多個環節實現,由此也可以將電子商務分為兩個層次,較低層次的電子商務如電子商情、電子貿易、電子合同等;最完整的也是最高級的電子商務應該是利用INTENET網路能夠進行全部的貿易活動,即在網上將信息流、商流、資金流和部分的物流完整地實現,也就是說,你可以從尋找客戶開始,一直到洽談、訂貨、在線付(收)款、開據電子發票以至到電子報關、電子納稅等通過INTERNET一氣呵成。
要實現完整的電子商務還會涉及到很多方面,除了買家、賣家外,還要有銀行或金融機構、政府機構、認證機構、配送中心等機構的加入才行。由於參與電子商務中的各方在物理上是互不謀面的,因此整個電子商務過程並不是物理世界商務活動的翻版,網上銀行、在線電子支付等條件和數據加密、電子簽名等技術在電子商務中發揮著重要的不可或缺的作用。
暈了,我是電子商務專業的,老師當時只是說可以到公司上班,為設計會議材料,安排會議室,再就是建網站,做做網頁