如何在Oracle/2000中調用Windows API函數
2024-08-29 13:41:11
供稿:網友
OracleDeveloper/2000是Oracle的微機開發工具,由于它與Oracle數據庫的緊密連接,比用PowerBuilder或其它高級語言采用ODBC與Oracle的連接享有得天獨厚的優點,越來越在Windows95和WindowsNT平臺上得到廣泛應用,筆者在用其進行程序設計時感到,既然是在Windows平臺上開發程序, 假如能在其中應用一些WindowsAPI函數,將使Developer/2000有如虎添翼的感覺,可以大大彌補它與底層操作系統的聯系能力差、控制實時硬件設備功能差的缺點,開發出集成性更好的應用程序。
所有用第三方語言編寫的子程序對Developer/2000都稱為外部函數,WindowsAPI函數也是外部函數。這些外部函數必須包含在一個動態庫中。例如WINDOWS操作系統下的動態鏈接庫或UNIX系統下的共享庫等。Developer/2000通過為每一個外部函數產生一個PL/SQL接口,它使用PL/SQL的語法,在程序中調用這一接口程序就可以激活這一外部函數。
對一個外部函數產生一個PL/SQL接口,需要用到內建軟件包ORA-FFI,它包含一些PL/SQL的子程序用來對外部函數生成PL/SQL接口,實際操作時可以用PRocedureBuilder產生一個程序庫,在程序庫中建立一個程序包(Package),在這個包中實現對外部函數建立連接。下面介紹這一過程的具體步驟:
1.初始化外部函數
就是說明包含外部函數的動態鏈接庫的位置,并從中分離出外部函數的原型,并將外部函數中主語言的數據類型和PL/SQL數據類型做一一對應的匹配。這是在包體(PackageBody)中進行的。具體分以下幾步:
(1)用OQA_FFI.LOAD_LIBRARY得到包含外部函數的動態鏈接庫的庫柄,此時需提供動態鏈接庫的名字和位置。
(2)用ORA_FFI.REGISTER_FUNCTION得到外部函數的函數柄,這時需提供動態鏈接庫的庫柄和外部函數名。
(3)用ORA_FFI.REGISTER_PARAMETER來注冊外部函數的參數類型,對每一個參數都要提供它的外部函數柄和相應的PL/SQL數據類型。參數注冊的順序必須與它們出現在外部函數原型中的順序一致。
(4)用ORA_FFI.REGISTER_RETURN來注冊外部函數的返回值類型,這時需要提供它的外部函數柄和相應的PL/SQL數據類型。
2.將外部函數和一個PL/SQL子程序相關聯
一個和外部函數建立關聯的PL/SQL子程序,實際上指明了外部函數的內存地址,每次調用這個子程序,實際上是調用與它相對應的外部函數。具體步驟為:
(1)用ORA_FFI.FIND_FUNCTION或ORA_FFI.REGISTER_FUNCTION得到一個函數柄。
(2)在PL/SQL包體的聲明部分,定義一個PL/SQL子程序,它的第一個參數是類型為ORA_FFI.FUNCHANDLETYPE,接下來是依次對應外部函數參數的PL/SQL數據類型的參數。
(3)在這個PL/SQL子程序中加入一個PRAGMA接口。PRAGMA聲明就是通過將控制轉到一個內存地址,來激活這個外部函數。
3.生成一個模擬外部函數的原型的PL/SQL子程序。
這個子程序就是用戶可見的外部函數的PL/SQL接口,用戶按照它的參數類型和返回值類型來使用外部函數,具體步驟為:
(1)在包體的聲明部分,定義一個PL/SQL子程序,它的參數和返回值是和外部函數對應的PL/SQL類型。這就是模擬外部函數原型的一個子程序。
(2)在這個子程序中調用與上步生成的與外部函數相關聯的PL/SQL子程序。
(3)在PL/SQL包的說明(PackageSpefication)部分,輸入這個PL/SQL子程序的原型。
下面是一個完整的為WindowsAPI函數winexec建立PL/SQL接口的例子:
PACKAGEWinExecIS
FUNCTIONWinExec(ExecfileINVARCHAR2,
commandINPLS_INTEGER)
RETURNPLS_INTEGER;
END;/*在包說明部分,是模擬外部
函數原型的PL/SQL函數原型說明*/
PACKAGEBODYWinExecIS
lh_USERora_ffi.libHandleType;/*定義庫柄類型變量*/
fh_WinExecora_ffi.funcHandleType;/*定義函數柄類型變量*/
FUNCTIONi_WinExec(funcHandleINora_ffi.funcHandleType,
ExecfileINOUTVARCHAR2,
commandINPLS_INTEGER)
RETURNPLS_INTEGER;
PRAGMAINTERFACE(C,i_WinExec,11265);
/*步驟2將一個PL/SQL子程序與外部函數相關聯*/
FUNCTIONWinExec(ExecfileINVARCHAR2,
commandINPLS_INTEGER)
RETURNPLS_INTEGER
IS
execfile_lVARCHAR2(512):=Execfile;
rcPLS_INTEGER;
BEGIN
rc:=i_WinExec(fh_WinExec,
execfile_l,
command);
RETURN(rc);
END;
/*步驟3中PL/SQL模擬函數的定義,
它實際上就是調用步驟2中與外部函數建立關聯的那個函數*/
BEGIN
BEGIN
lh_USER:=ora_ffi.find_library('Kernel32.dll');
EXCEPTIONWHENora_ffi.FFI_ERRORTHEN
lh_USER:=ora_ffi.load_library(NULL,'kernel32.dll');
END;/*得到動態鏈接庫的庫柄*/
fh_WinExec:=ora_ffi.register_function
(lh_USER,'WinExec',ora_ffi.PASCAL_STD);
/*得到外部函數的函數柄*/
ora_ffi.register_parameter(fh_WinExec,
ORA_FFI.C_CHAR_PTR);/*參數注冊,原類型為LPCSTR*/
ora_ffi.register_parameter(fh_WinExec,
ORA_FFI.C_INT);/*參數注冊,原類型為UINT*/
ora_ffi.register_return(fh_WinExec,
ORA_FFI.C_INT);/*返回值注冊,原類型為BOOL*/
ENDWinExec;
可以將多個外部函數的PL/SQL接口放在一個包內。
要在Developer/2000的FormDesigner中使用這些外部函數,只要把包含這一程序包的程序庫(.PLL)附加進來,使用包名.函數名就可激活這個外部函數。
例如:WinExec.WinExec('c:/windows/notepad.exe',0)
具體WindowsAPI函數數據類型和PL/SQL數據類型的轉換可參照Developer/2000中ProcedureBuilder幫助文件中對ORA_FFI軟件包的具體介紹。