Oracle Developer/2000(含 Forms/Reports)與資料庫緊密整合,開發效率高。但其屬於中介軟體層,對底層作業系統(檔案系統、登錄、硬體裝置、視窗控制等)存取能力有限。透過呼叫 Windows API(動態連結庫 DLL 中的函數),可彌補此短板,實現:啟動外部程式、操作登錄、控制硬體、進階視窗操作等功能,大幅擴展應用程式整合性。
ORA_FFI(Foreign Function Interface)為每個外部函數產生 PL/SQL 介面(Wrapper)。ORA_FFI.LOAD_LIBRARY:載入 DLL,取得 Library Handle。ORA_FFI.REGISTER_FUNCTION:註冊函數,取得 Function Handle。ORA_FFI.REGISTER_PARAMETER:依原型順序註冊每個參數,對應 PL/SQL 資料型別。ORA_FFI.REGISTER_RETURN:註冊回傳值型別。ORA_FFI.FUNCHANDLETYPE,其後依序為對應參數型別。PRAGMA INTERFACE(C, <proc_name>, <address>) 指定記憶體位址(或由 ORA_FFI 解析)。WinExec(啟動外部程式)PACKAGE WinExec IS
FUNCTION WinExec(p_execfile IN VARCHAR2, p_cmdshow IN PLS_INTEGER) RETURN PLS_INTEGER;
END WinExec;
/
PACKAGE BODY WinExec IS
v_lib ORA_FFI.LIBHANDLETYPE;
v_func ORA_FFI.FUNCHANDLETYPE;
-- 步驟 2:關聯外部函數的內部子程序
FUNCTION i_WinExec(p_func IN ORA_FFI.FUNCHANDLETYPE,
p_file IN OUT VARCHAR2,
p_show IN PLS_INTEGER) RETURN PLS_INTEGER;
PRAGMA INTERFACE(C, i_WinExec, 11265); -- 位址由 ORA_FFI 解析
-- 步驟 3:對外公開的 Wrapper
FUNCTION WinExec(p_execfile IN VARCHAR2, p_cmdshow IN PLS_INTEGER) RETURN PLS_INTEGER IS
v_file VARCHAR2(512) := p_execfile;
v_rc PLS_INTEGER;
BEGIN
v_rc := i_WinExec(v_func, v_file, p_cmdshow);
RETURN v_rc;
END WinExec;
-- 初始化區塊:載入 DLL、註冊函數與參數
BEGIN
BEGIN
v_lib := ORA_FFI.FIND_LIBRARY('Kernel32.dll');
EXCEPTION
WHEN ORA_FFI.FFI_ERROR THEN
v_lib := ORA_FFI.LOAD_LIBRARY(NULL, 'kernel32.dll');
END;
v_func := ORA_FFI.REGISTER_FUNCTION(v_lib, 'WinExec', ORA_FFI.PASCAL_STD); -- __stdcall 慣例
ORA_FFI.REGISTER_PARAMETER(v_func, ORA_FFI.C_CHAR_PTR); -- LPCSTR lpCmdLine
ORA_FFI.REGISTER_PARAMETER(v_func, ORA_FFI.C_INT); -- UINT uCmdShow
ORA_FFI.REGISTER_RETURN(v_func, ORA_FFI.C_INT); -- BOOL 回傳
END WinExec;
/
| C/C++ 型別 | ORA_FFI 常數 | PL/SQL 型別 |
|---|---|---|
| LPCSTR / LPSTR | ORA_FFI.C_CHAR_PTR | VARCHAR2 |
| INT / UINT / LONG / DWORD | ORA_FFI.C_INT | PLS_INTEGER / NUMBER |
| BOOL | ORA_FFI.C_INT | PLS_INTEGER |
| HWND / HANDLE | ORA_FFI.C_POINTER | PLS_INTEGER (視為指標) |
| LPVOID | ORA_FFI.C_POINTER | PLS_INTEGER |
完整對照請參閱 Procedure Builder 線上說明「ORA_FFI Package」。
WinExec.WinExec('c:\windows\notepad.exe', 1);(1 = SW_SHOWNORMAL)。__stdcall(PASCAL_STD),若為 __cdecl 需用 ORA_FFI.CDECL。OUT 或 IN OUT 字串參數時,PL/SQL 端需預先分配足夠長度(如 v_buf VARCHAR2(1024) := LPAD(' ', 1024))。GetLastError(另行包裝)。C:\Windows\SysWOW64 有對應 DLL。善用 ORA_FFI 將 Windows API 包裝為 PL/SQL 介面,能讓 Oracle Developer/2000 突破中介層限制,直接操作作業系統資源。掌握「載入→註冊→包裝」三步驟與型別對照,即可安全、穩定地擴展應用功能,實現與底層硬體、外部程式的深度整合。