Lv.的博客

Pro*C编程研究一:从.pc到.exe

【第一步】在Windows下编辑一个.pc程序(Pro*C源程序,作者用到:C:\proctest\exam1.pc),其内容如下: 

[cpp] view plaincopy
 
  1. #include <stdio.h>  
  2. #include <string.h>  
  3.   
  4. EXEC SQL INCLUDE SQLCA;  
  5.   
  6. int main()  
  7. {  
  8.    /*declare variables*/  
  9.    EXEC SQL BEGIN DECLARE SECTION;  
  10.    VARCHAR usr[20], pass[20], serv[20];     
  11.    char name[8];  
  12.    int age;    
  13.    EXEC SQL END DECLARE SECTION;    
  14.      
  15.    /*connect DB*/  
  16.    strcpy(usr.arr,"any3");  
  17.    usr.len=(unsigned short)strlen((char *)usr.arr);  
  18.    strcpy(pass.arr,"any3");  
  19.    pass.len=(unsigned short)strlen((char *)pass.arr);  
  20.    strcpy(serv.arr,"ORCL");  
  21.    serv.len=(unsigned short)strlen((char *)serv.arr);  
  22.     
  23.    /*Connecting DB Command*/  
  24.    EXEC SQL CONNECT :usr IDENTIFIED BY :pass USING :serv;  
  25.    printf("Connect!\n");  
  26.     
  27.     /*Input*/  
  28.     printf("Input Member Age:");  
  29.     scanf("%d", &age);  
  30.        
  31.    /*Exec SQL*/  
  32.    EXEC SQL SELECT age, name into :age, :name from family_lu where age=:age;  
  33.    printf("Name=%s    ,Age=%d\n", name, age);  
  34.     
  35.     /*commit and disconnect DB*/  
  36.     EXEC SQL COMMIT WORK RELEASE;  
  37.     printf("Disconnect!\n");  
  38.       
  39.     return 1;  
  40. }  

 

 作者机器上使用到的oracle实例ORCL,并以用户名/密码(any3/any3)登陆。

为示例,作者建立测试数据表 family_lu ,其结构明细为:

CREATE TABLE family_lu
(
       age   number,
       name  varchar2(20),
       reltn varchar2(20)          
);

插入数据:

insert into family_lu values(0, 'anan', 'child');

 

【第二步】在Windows下使用Oracle数据库的...\bin\Proc.exe预编译该.pc文件,生成对应的.c源程序。

 

【建议一】

注意到安装Oracle时已经将“D:\oracle\product\10.2.0\db_1\bin;”自动添加到“系统环境变量->系统变量->Path”中,因此,在“开始->运行->cmd”回车后,直接进入到.pc文件所在路径,输入proc命令。

如本人Win7系统下为:

C:\Users\Administrator>cd ../../proctest

然后输入命令:proc exam1.pc

 

【第三步】使用Windows下的gcc编译器对上述.c源文件进行编译,并生成windows下的可执行文件。

注意到这里是最容易报错(非犯错)的地方!!!

 

【建议二】使用最新的gcc编译器。

对于较低版本的gcc,对于这一段源程序

usr.len=(unsigned short)strlen((char *)usr.arr);

编译会报错:

invalid conversion from `const char*' to `char*'

而升级到最新编译器则不存在此问题

——当然也可能是编码时语法不严谨导致,但无论如何,最新的编译器可用性更好,并且向下兼容。

作者机器上安装了JFE and GCC,它自动被添加到了“系统环境变量->系统变量->Path”中,但其版本较低。

这里手动将“D:\Program Files\CodeBlocks\MinGW\bin;”添加到“系统环境变量->系统变量->Path”的最前方(注意MinGW已经安装在本机上,为作者安装CodeBlocks时自带),即对于同名的gcc编译器,希望调用Path中靠前的那一个。MinGW的GCC编译器版本为4.7.1。

 

【建议三】使用正确的库文件

对于.pc源程序中有SQL(DB连接、数据查询等)相关代码的,在Pro*C将.pc转化为.c时,会自动在.c文件中声明并引用

extern void sqlcxt (void **, unsigned int *,  struct sqlexd *, const struct sqlcxp *);

extern void sqlcx2t(void **, unsigned int *, struct sqlexd *, const struct sqlcxp *);
extern void sqlbuft(void **, char *);
extern void sqlgs2t(void **, char *);
extern void sqlorat(void **, unsigned int *, void *);

等相关函数,因为在简单的Pro*C编程示例中,在.pc预编译成.c文件后,多数情况下都只使用了sqlcxt函数(而未使用sqlbuft等),因此,gcc在编译.c时将报错:

undefined reference to `sqlcxt(void**, unsigned*, sqlexd*, sqlcxp const*)'

这是由于gcc在编译时未加入Pro*C指定的库文件(静态库.lib或动态连接库.dll),该库包括了sqlcxt的定义。

由于Pro*C广泛应用于Linux+Oracle环境,因此在多数博客文章或论坛发帖中,常见到:

////////////引用部分开始////////////

需要用到$ORACLE_HOME/lib/libclntsh.so
故需加上 -L $ORACLE_HOME/lib -l clntsh
更正后的命令为:
gcc -o test test.c -I /home/oracle/oracle/product/10.2.0/db_1/precomp/public -L $ORACLE_HOME/lib -l clntsh

////////////引用部分结束////////////LINK: http://blog.chinaunix.net/uid-261392-id-2138943.html

 

在百度中搜索关键字“windows libclntsh”,非常好运地找到了《OCI Instant Client》 LINK:http://www.cnblogs.com/freewater/archive/2011/08/09/2132801.html

作者找到Linux和Unix下的libclntsh.so.11.1(.so是Linux等下的动态连接库),正好对应于Windows下的oci.dll。

 

最后,在《gcc编译dll和调用dll》一文中

LINK:http://blog.csdn.net/denglei265/article/details/3889470

找到调用.dll库文件生成windows下可执行文件的(简单)方法,如作者使用命令:

C:\proctest>gcc exam1.c D:\oracle\product\10.2.0\db_1\BIN\oci.dll -o exam1

成功生成可执行文件,运行之得到效果:

C:\proctest>exam1
Connect!
Input Member Age:0
Name=anan       ,Age=0
Disconnect!

而这恰好是本文Pro*C程序示例希望实现的效果!

posted @ 2014-05-27 15:00  Avatarx  阅读(541)  评论(0编辑  收藏  举报