1. 苏葳的备忘录首页
  2. 编程

嵌入式Python中引用Pro *C主程序中建立的数据库链接

oracle python pro_cPython之所以被称为“胶水语言”,是因为它与其它语言之间良好的互操作性。可以在Python中方便的调用其它语言的模块,如C语言的Dll或SO等,而Python语言也可以以嵌入方式被其它语言调用并运行。相当于启动了一个内置的Python语言解释环境。那么问题来了,我们固然可以通过参数方式把宿主语言的变量传入Python,但是宿主语言如Pro *C如果创建了数据库连接的话,连接句柄如何传入嵌入式Python里呢?

首先如何判断被调用者跟调用者使用的是同一数据库链接?

# query = "select sid from v$mystat where rownum=1"
query = "select userenv('sid') from dual"

两种方法都可,可能其中有些方法有oracle版本要求。

在pro c主程序中使用sql exec connect to建立连接后,执行上述语句,打印出sid 值,然后在被调用的python子程序中,尝试引用主程序传入的数据库连接,然后再打印一次sid值,如果多次运行后两个sid值都相同,可以认为引用成功,若每次运行两个sid值都不同,则可认为是两个不同的连接,即引用未成功。

现在pro c 程序中,首先要取得一个值OCISvcCtx *svchp; 此值实际就是数据库的连接句柄。此值及稍后用到的函数在oracle头文件sql2oci.h中定义,然后使用函数:

rc = SQLSvcCtxGet(0, (text *)0, (sb4)0, (OCISvcCtx **) &svchp);
 if (rc)
 {
  vLog(LOG_ERROR, "获取sql句柄时出错,错误码[%d]",rc);
  TRACE_END(DO_FAIL);
 }

获取svchp,注意也有更简单的调用方法:

retcode=SQLSvcCtxGet(0,0,-1,&svchp); // get an OCI formatted service
                                        // context handle from the
                                        // primary connection
   if(retcode!=SQL_SUCCESS){
    cerr<<"Failed to get the service context handle!!!"<<endl;
    return 1;
   }

也有更严谨的方法,此处不提。

此时,获得一个svchp指针,注意在64位编译环境下(RHEL 5.5 64位版默认编译器64位,等同于-m64选项)此指针值为8字节,需用一个long型8字节数保存。

然后就是将此值传入以嵌入方法调用的python子程序,此处有个问题,若是非嵌入方式调用,能否通过传入此数据连接的句柄,使进程外的另一进程使用此进程内的数据连接?没试过,等遇到再说吧。

简单的使用Py_BuildValue(“l”,svchp),将此句柄作为一个长整型数处理。传入子程序的testlong参数。

然后在cx_Oracle连接创建语句中:

# db=cx_Oracle.connect('bidb','bidb','BI155')
db=cx_Oracle.connect('bidb','bidb','BI155',handle=testlong)

注意两者区别,仅在于是否使用了handle参数,事实上,将前几个参数省略掉可否?既已有句柄,不就拥有数据库操作所需的一切了?未测试过。或者connect会用前三个参数作些校验也未可知。

然后用本文开始处的方法,调用sql语句显示sid,分别用加handle和不加handle的connect方法,证实了handle参数确实起到了作用。

原创文章,作者:苏葳,如需转载,请注明出处:https://www.swmemo.com/419.html

发表评论

邮箱地址不会被公开。 必填项已用*标注