Oracle 调用Windows动态链接库.
更确切地说是调用动态链接库中的某一个函数
Oracle是通过创建一个别名函数或者存储过程(以下统称子程序)来达到调用动态链接库的目的。
该函数或者存储过程定义了与外部函数的影射关系,包括
1.返回值
2.参数映射
3.外部函数的名称
4.外部函数的所属的动态链接库文件
这有一点类似于C#中调用Windows动态链接库.
具体的步骤就是
1.创建Oracle Library
Create Library LIBTESTPROC as 'C:\UserData\xuxia\TestProc\Debug\TestProc.dll'
2.给具体使用这个Library的用户以执行权限
Grant Execute LIBTESTPROC to [UserName]
3.定义Oracle 子程序
CREATE OR REPLACE Function fnTestProc
Return Binary_Integer
As Language C
library LibTestProc
Name "fnTestProc";
如果你认为这样定义一下就好了,那就大错特错了。
Oracle把这一功能搞得有点复杂化了。为什么就不能像MS SQL 定义扩展存储过程那样简单一点呢?
Oracle就是拽。 为了完成这一任务,你必须对Orcale调用Windows动态链接库的机制
作一了解如下:
1.客户端程序执行一段Pl/SQL 程序
2.Server Process 发现有调用外部函数的子程序
3.Server Process 把请求发送给Oracle监听程序
4.Oracle监听程序将启动extproc. 该进程直到会话结束才会中止。
5.extproc装载动态链接库
6.extproc 找到匹配的函数执行
7.extproc 将执行结果发送给Server Process
从上面这个机制,你就知道Extproc进程是必不可少的。但是并不是所有的Oracle监听器都配置了ExtProc,
可以参考下面的文章
http://download.oracle.com/docs/cd/B10501_01/network.920/a96580/advcfg.htm#483609
如果你的监听器没有配置ExtProc,
将会发生
ORA-28575 unable to open RPC connection to external procedure agent
但是仅仅监听器设置了这个还是不用的
必须在Oracle 服务器端(注意不是其他机器上)的TNSNames.ora文件添加特别的Oracle LocalName:
EXTPROC_CONNECTION_DATA =
(DESCRIPTION =
(ADDRESS_LIST =
(ADDRESS = (PROTOCOL = IPC)(KEY = EXTPROC))
)
(CONNECT_DATA =
(SID = PLSExtProc)
(PRESENTATION = RO)
)
)
只有这样才不会继续发生ORA-28575 unable to open RPC connection to external procedure agent的错误
到了这里,似乎一切OK了,但是下面还有更要命的错误等着你呢?
ORA-28576 lost RPC connection to external procedure agent
这个错误让人多摸不着头脑。Oracle官方网站的解释也是非常模糊
Cause: A fatal error occurred in either an RPC network connection, the external procedure agent, or the invoked 3GL after communication had been established successfully.
Action: First check the 3GL code you are invoking; the most likely cause of this error is abnormal termination of the invoked "C" routine. If this is not the case, check for network problems. Correct the problem if you find it. If all components appear to be normal but the problem persists, the problem could be an internal logic error in the RPC transfer code. Contact Oracle Support Services.
意思似乎是外部链接库的某些问题也会导致这样的错误。
后来知道了Oracle调用外部程序有两种方式一种是标准的C调用,一种是Pascal调用。缺省是标准的C调用.不支持stdcall。
Pascal调用方式在VC里已经不支持了。所以如果你的程序是用VC开发的,唯一的办法就是
修改你的动态链接库源代码,改为标准的C调用,重新编译
Example:
TESTPROC_API int fnTestProc(void); ==>
extern "C"
{
TESTPROC_API int fnTestProc(void);
}
如果你就想调用没有源代码的动态链接库怎么办,因为大部分Windows下的动态链接库都是定义成 stdcall方式的,所以
你只能自己创建一个动态链接库工程,然后封装没有源代码的动态链接库函数。
更确切地说是调用动态链接库中的某一个函数
Oracle是通过创建一个别名函数或者存储过程(以下统称子程序)来达到调用动态链接库的目的。
该函数或者存储过程定义了与外部函数的影射关系,包括
1.返回值
2.参数映射
3.外部函数的名称
4.外部函数的所属的动态链接库文件
这有一点类似于C#中调用Windows动态链接库.
具体的步骤就是
1.创建Oracle Library
Create Library LIBTESTPROC as 'C:\UserData\xuxia\TestProc\Debug\TestProc.dll'
2.给具体使用这个Library的用户以执行权限
Grant Execute LIBTESTPROC to [UserName]
3.定义Oracle 子程序
CREATE OR REPLACE Function fnTestProc
Return Binary_Integer
As Language C
library LibTestProc
Name "fnTestProc";
如果你认为这样定义一下就好了,那就大错特错了。
Oracle把这一功能搞得有点复杂化了。为什么就不能像MS SQL 定义扩展存储过程那样简单一点呢?
Oracle就是拽。 为了完成这一任务,你必须对Orcale调用Windows动态链接库的机制
作一了解如下:
1.客户端程序执行一段Pl/SQL 程序
2.Server Process 发现有调用外部函数的子程序
3.Server Process 把请求发送给Oracle监听程序
4.Oracle监听程序将启动extproc. 该进程直到会话结束才会中止。
5.extproc装载动态链接库
6.extproc 找到匹配的函数执行
7.extproc 将执行结果发送给Server Process
从上面这个机制,你就知道Extproc进程是必不可少的。但是并不是所有的Oracle监听器都配置了ExtProc,
可以参考下面的文章
http://download.oracle.com/docs/cd/B10501_01/network.920/a96580/advcfg.htm#483609
如果你的监听器没有配置ExtProc,
将会发生
ORA-28575 unable to open RPC connection to external procedure agent
但是仅仅监听器设置了这个还是不用的
必须在Oracle 服务器端(注意不是其他机器上)的TNSNames.ora文件添加特别的Oracle LocalName:
EXTPROC_CONNECTION_DATA =
(DESCRIPTION =
(ADDRESS_LIST =
(ADDRESS = (PROTOCOL = IPC)(KEY = EXTPROC))
)
(CONNECT_DATA =
(SID = PLSExtProc)
(PRESENTATION = RO)
)
)
只有这样才不会继续发生ORA-28575 unable to open RPC connection to external procedure agent的错误
到了这里,似乎一切OK了,但是下面还有更要命的错误等着你呢?
ORA-28576 lost RPC connection to external procedure agent
这个错误让人多摸不着头脑。Oracle官方网站的解释也是非常模糊
Cause: A fatal error occurred in either an RPC network connection, the external procedure agent, or the invoked 3GL after communication had been established successfully.
Action: First check the 3GL code you are invoking; the most likely cause of this error is abnormal termination of the invoked "C" routine. If this is not the case, check for network problems. Correct the problem if you find it. If all components appear to be normal but the problem persists, the problem could be an internal logic error in the RPC transfer code. Contact Oracle Support Services.
意思似乎是外部链接库的某些问题也会导致这样的错误。
后来知道了Oracle调用外部程序有两种方式一种是标准的C调用,一种是Pascal调用。缺省是标准的C调用.不支持stdcall。
Pascal调用方式在VC里已经不支持了。所以如果你的程序是用VC开发的,唯一的办法就是
修改你的动态链接库源代码,改为标准的C调用,重新编译
Example:
TESTPROC_API int fnTestProc(void); ==>
extern "C"
{
TESTPROC_API int fnTestProc(void);
}
如果你就想调用没有源代码的动态链接库怎么办,因为大部分Windows下的动态链接库都是定义成 stdcall方式的,所以
你只能自己创建一个动态链接库工程,然后封装没有源代码的动态链接库函数。