作者
王 瑩( 山 東 工 業 大 學 碩 士 研 究 生)
Oracle Developer/
是Oracle 的 微 機 開 發 工 具
由 於 它 與Oracle 數 據 庫 的 緊 密 連 接
比 用Power Builder 或 其 它 高 級 語 言 采 用ODBC 與Oracle 的 連 接 享 有 得 天 獨 厚 的 優 點
越 來 越 在Windows
和WindowsNT 平 台 上 得 到 廣 泛 應 用
筆 者 在 用 其 進 行 程 序 設 計 時 感 到
既 然 是 在Windows 平 台 上 開 發 程 序
如 果 能 在 其 中 應 用 一 些Windows API 函 數
將 使Developer/
有 如 虎 添 翼 的 感 覺
可 以 大 大 彌 補 它 與 底 層 操 作 系 統 的 聯 系 能 力 差
控 制 實 時 硬 件 設 備 功 能 差 的 缺 點
開 發 出 集 成 性 更 好 的 應 用 程 序
所 有 用 第 三 方 語 言 編 寫 的 子 程 序 對Developer/
都 稱 為 外 部 函 數
Windows API 函 數 也 是 外 部 函 數
這 些 外 部 函 數 必 須 包 含 在 一 個 動 態 庫 中
例 如WINDOWS 操 作 系 統 下 的 動 態 鏈 接 庫 或UNIX 系 統 下 的 共 享 庫 等
Developer/
通 過 為 每 一 個 外 部 函 數 產 生 一 個PL/SQL 接 口
它 使 用PL/SQL 的 語 法
在 程 序 中 調 用 這 一 接 口 程 序 就 可 以 激 活 這 一 外 部 函 數
對 一 個 外 部 函 數 產 生 一 個PL/SQL 接 口
需 要 用 到 內 建 軟 件 包ORA
FFI
它 包 含 一 些PL/SQL 的 子 程 序 用 來 對 外 部 函 數 生 成PL/SQL 接 口
實 際 操 作 時 可 以 用Procedure Builder 產 生 一 個 程 序 庫
在 程 序 庫 中 建 立 一 個 程 序 包(Package)
在 這 個 包 中 實 現 對 外 部 函 數 建 立 連 接
下 面 介 紹 這 一 過 程 的 具 體 步 驟
初 始 化 外 部 函 數
就 是 說 明 包 含 外 部 函 數 的 動 態 鏈 接 庫 的 位 置
並 從 中 分 離 出 外 部 函 數 的 原 型
並 將 外 部 函 數 中 主 語 言 的 數 據 類 型 和PL/SQL 數 據 類 型 做 一 一 對 應 的 匹 配
這 是 在 包 體(Package Body) 中 進 行 的
具 體 分 以 下 幾 步
(
) 用OQA_FFI
LOAD_LIBRARY 得 到 包 含 外 部 函 數 的 動 態 鏈 接 庫 的 庫 柄
此 時 需 提 供 動 態 鏈 接 庫 的 名 字 和 位 置
(
) 用ORA_FFI
REGISTER_FUNCTION 得 到 外 部 函 數 的 函 數 柄
這 時 需 提 供 動 態 鏈 接 庫 的 庫 柄 和 外 部 函 數 名
(
) 用ORA_FFI
REGISTER_PARAMETER 來 注 冊 外 部 函 數 的 參 數 類 型
對 每 一 個 參 數 都 要 提 供 它 的 外 部 函 數 柄 和 相 應 的PL/SQL 數 據 類 型
參 數 注 冊 的 順 序 必 須 與 它 們 出 現 在 外 部 函 數 原 型 中 的 順 序 一 致
(
) 用ORA_FFI
REGISTER_RETURN 來 注 冊 外 部 函 數 的 返 回 值 類 型
這 時 需 要 提 供 它 的 外 部 函 數 柄 和 相 應 的PL/SQL 數 據 類 型
將 外 部 函 數 和 一 個PL/SQL 子 程 序 相 關 聯
一 個 和 外 部 函 數 建 立 關 聯 的PL/SQL 子 程 序
實 際 上 指 明 了 外 部 函 數 的 內 存 地 址
每 次 調 用 這 個 子 程 序
實 際 上 是 調 用 與 它 相 對 應 的 外 部 函 數
具 體 步 驟 為
(
) 用ORA_FFI
FIND_FUNCTION 或ORA_FFI
REGISTER_FUNCTION 得 到 一 個 函 數 柄
(
) 在PL/SQL 包 體 的 聲 明 部 分
定 義 一 個PL/SQL 子 程 序
它 的 第 一 個 參 數 是 類 型 為ORA_FFI
FUNCHANDLETYPE
接 下 來 是 依 次 對 應 外 部 函 數 參 數 的PL/SQL 數 據 類 型 的 參 數
(
) 在 這 個PL/SQL 子 程 序 中 加 入 一 個PRAGMA 接 口
PRAGMA 聲 明 就 是 通 過 將 控 制 轉 到 一 個 內 存 地 址
來 激 活 這 個 外 部 函 數
生 成 一 個 模 仿 外 部 函 數 的 原 型 的PL/SQL 子 程 序
這 個 子 程 序 就 是 用 戶 可 見 的 外 部 函 數 的PL/SQL 接 口
用 戶 按 照 它 的 參 數 類 型 和 返 回 值 類 型 來 使 用 外 部 函 數
具 體 步 驟 為
(
) 在 包 體 的 聲 明 部 分
定 義 一 個PL/SQL 子 程 序
它 的 參 數 和 返 回 值 是 和 外 部 函 數 對 應 的PL/SQL 類 型
這 就 是 模 仿 外 部 函 數 原 型 的 一 個 子 程 序
(
) 在 這 個 子 程 序 中 調 用 與 上 步 生 成 的 與 外 部 函 數 相 關 聯 的PL/SQL 子 程 序
(
) 在PL/SQL 包 的 說 明(Package Spefication) 部 分
輸 入 這 個PL/SQL 子 程 序 的 原 型
下 面 是 一 個 完 整 的 為Windows API 函 數winexec 建 立PL/SQL 接 口 的 例 子
PACKAGE WinExec IS
FUNCTION WinExec(Execfile IN VARCHAR
command IN PLS_INTEGER)
RETURN PLS_INTEGER;
END; /*在包說明部分
是模仿外部
函數原型的PL/SQL函數原型說明*/
PACKAGE BODY WinExec IS
lh_USER ora_ffi
libHandleType; /*定義庫柄類型變量*/
fh_WinExec ora_ffi
funcHandleType; /*定義函數柄類型變量*/
FUNCTION i_WinExec(funcHandle IN ora_ffi
funcHandleType
Execfile IN OUT VARCHAR
command IN PLS_INTEGER)
RETURN PLS_INTEGER;
PRAGMA INTERFACE(C
i_WinExec
);
/*步驟
將一個PL/SQL子程序與外部函數相關聯*/
FUNCTION WinExec(Execfile IN VARCHAR
command IN PLS_INTEGER)
RETURN PLS_INTEGER
IS
execfile_l VARCHAR
(
) := Execfile;
rc PLS_INTEGER;
BEGIN
rc := i_WinExec(fh_WinExec
execfile_l
command);
RETURN (rc);
END ;
/*步驟
中PL/SQL模仿函數的定義
它實際上就是調用步驟
中與外部函數建立關聯的那個函數*/
BEGIN
BEGIN
lh_USER := ora_ffi
find_library(
Kernel
dll
);
EXCEPTION WHEN ora_ffi
FFI_ERROR THEN
lh_USER := ora_ffi
load_library(NULL
kernel
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 */
END WinExec;
可 以 將 多 個 外 部 函 數 的PL/SQL 接 口 放 在 一 個 包 內
要 在Developer/
的Form Designer 中 使 用 這 些 外 部 函 數
只 要 把 包 含 這 一 程 序 包 的 程 序 庫(
PLL) 附 加 進 來
使 用 包 名
函 數 名 就 可 激 活 這 個 外 部 函 數
例 如
WinExec
WinExec(
c:\windows\notepad
exe
)
具 體Windows API 函 數 數 據 類 型 和PL/SQL 數 據 類 型 的 轉 換 可 參 照 Developer/
中Procedure Builder 幫 助 文 件 中 對ORA_FFI 軟 件 包 的 詳 細 介 紹
From:http://tw.wingwit.com/Article/program/Oracle/201311/18278.html