首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 數據庫知識 >  >> Oracle 資料庫 >> Oracle 資料庫基礎

Oracle Developer/2000 呼叫 Windows API 函數完整教學

     編輯:Oracle 資料庫基礎

前言:為何在 Developer/2000 中呼叫 Windows API?

Oracle Developer/2000(含 Forms/Reports)與資料庫緊密整合,開發效率高。但其屬於中介軟體層,對底層作業系統(檔案系統、登錄、硬體裝置、視窗控制等)存取能力有限。透過呼叫 Windows API(動態連結庫 DLL 中的函數),可彌補此短板,實現:啟動外部程式、操作登錄、控制硬體、進階視窗操作等功能,大幅擴展應用程式整合性。

核心架構:外部函數與 ORA_FFI 套件

  • 所有第三方函數(含 Windows API)對 Developer/2000 均為「外部函數」。
  • 外部函數必須置於動態連結庫(DLL)中。
  • Developer/2000 透過內建套件 ORA_FFI(Foreign Function Interface)為每個外部函數產生 PL/SQL 介面(Wrapper)。
  • 呼叫流程:PL/SQL 程式 → PL/SQL Wrapper → ORA_FFI → DLL 外部函數。

三大步驟建立 PL/SQL 介面

步驟 1:初始化外部函數(於 Package Body 執行區)

  1. ORA_FFI.LOAD_LIBRARY:載入 DLL,取得 Library Handle。
  2. ORA_FFI.REGISTER_FUNCTION:註冊函數,取得 Function Handle。
  3. ORA_FFI.REGISTER_PARAMETER:依原型順序註冊每個參數,對應 PL/SQL 資料型別。
  4. ORA_FFI.REGISTER_RETURN:註冊回傳值型別。

步驟 2:建立與外部函數關聯的 PL/SQL 子程序

  • 於 Package Body 宣告區定義子程序,第一參數為 ORA_FFI.FUNCHANDLETYPE,其後依序為對應參數型別。
  • 加入 PRAGMA INTERFACE(C, <proc_name>, <address>) 指定記憶體位址(或由 ORA_FFI 解析)。

步驟 3:建立使用者可見的 PL/SQL Wrapper 函數

  • 參數與回傳型別模擬外部函數原型(使用 PL/SQL 原生型別)。
  • 本體中呼叫步驟 2 的子程序。
  • 於 Package Spec 宣告此函數原型,供表單/報表呼叫。

完整範例:包裝 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;
/

型別對照表(常用 Windows API → ORA_FFI 常數)

C/C++ 型別ORA_FFI 常數PL/SQL 型別
LPCSTR / LPSTRORA_FFI.C_CHAR_PTRVARCHAR2
INT / UINT / LONG / DWORDORA_FFI.C_INTPLS_INTEGER / NUMBER
BOOLORA_FFI.C_INTPLS_INTEGER
HWND / HANDLEORA_FFI.C_POINTERPLS_INTEGER (視為指標)
LPVOIDORA_FFI.C_POINTERPLS_INTEGER

完整對照請參閱 Procedure Builder 線上說明「ORA_FFI Package」。

在 Forms/Reports 中使用

  1. 將上述 Package 編譯並存入程式庫(.PLL)。
  2. 於表單/報表中 附加程式庫(File → Attach Library)。
  3. 呼叫語法:WinExec.WinExec('c:\windows\notepad.exe', 1);(1 = SW_SHOWNORMAL)。

常見陷阱與最佳實務

  • 呼叫慣例:Windows API 多為 __stdcall(PASCAL_STD),若為 __cdecl 需用 ORA_FFI.CDECL。
  • 字串緩衝區:傳入 OUT 或 IN OUT 字串參數時,PL/SQL 端需預先分配足夠長度(如 v_buf VARCHAR2(1024) := LPAD(' ', 1024))。
  • 錯誤處理:外部函數失敗不會拋出 PL/SQL 例外,需檢查回傳值或 GetLastError(另行包裝)。
  • 64 位元相容:Developer/2000 為 32 位元,僅能載入 32 位元 DLL;若環境為 64 位元 OS,確認 C:\Windows\SysWOW64 有對應 DLL。
  • 部署:隨應用程式散佈所需 DLL(若非系統內建),並確認目標機器 PATH 包含 DLL 目錄。

總結

善用 ORA_FFI 將 Windows API 包裝為 PL/SQL 介面,能讓 Oracle Developer/2000 突破中介層限制,直接操作作業系統資源。掌握「載入→註冊→包裝」三步驟與型別對照,即可安全、穩定地擴展應用功能,實現與底層硬體、外部程式的深度整合。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved