本篇文章来源于 Linux公社网站(www.linuxidc.com) 原文链接:http://www.linuxidc.com/Linux/2011-05/35930.htm
有点空,和新上手occi的筒子们一起总结下。这篇内容其实挺有用的,对于新人来说不管哪一方面都是一个难点,如oracle、unix、c++与occi、shell、makefile、随便挑出一个名词就能够让人学上一阵子了。这篇文章呢,咱就来个彻底的大剖析,目的是连通oracle并进行C++的应用编程,并在这个基础上,对我们以后每个名词点的深入学习,提供入门的作用。
首先说一下我的环境,(注:大家的工作环境千差万别,但万变不离其宗,今天着重讲这个宗,所以不必拘泥于环境如何,看了我的操作,希望能使你举一反三,各种环境都能应对自如。)由于公司结构不得不形成如下的工作环境:
本人主机:windows+secureCRT,所以我都是在使用远程
工作主机:unix+oracle(本人是oracle服务器端,其实客户端的问题不大后详细解释。)
数据库服务器:我只知道主机ip、数据库用户名及密码,其他都不知道。应该是大型主机。
这种环境貌似是三方,而实际工作是两方,因为我是用windows+secureCRT远程连接到unix工作机上,在unix上编写c++程序调用occi连接远程数据库服务器。所以描述重心是后两者的工作。至于secureCRT(可以是其他ssh工具)连接到unix则需要unix主机的ip地址、用户名及密码即可。
好了,下面的所有工作都是从登陆unix工作机这一刻开始,目标是在unix上编写一段连接远程oracle数据库的c++代码编译、连接、运行成功。各个击破吧!
第一步:编译、连接、运行C++程序,保证C++环境正确。
判断C++环境正确很简单,写个helloworld.cpp程序。代码如:
#include <iostream> using namespace std; main() { cout<<"hello world!"<<endl; }
这段代码要包含区别于c的元素,如using语句、cout等;CC -c helloworld.cpp
(
注意此处为大写的CC,小写的cc是编译c语言的)。结果会生成helloworld.o文件,继续运行连接命令:
结果会默认生成a.out文件,此时当前目录下执行 ./a.out 出现打印的hello world!则为成功了(不要漏掉点和斜杠./),C++的编译环境就这样完成了。
unix默认都会支持CC的,至于gcc那是linux上的gnu项目开发的unix不一定支持。
第二步:环境变量配置及撰写Makefile文件
1、Unix环境变量的配置ORACLE_HOME = /opt/app/ora10g/product/10.2.0; export ORACLE_HOME
PATH = /usr/ccs/bin:$ORACLE_HOME/bin:$PATH; export PATH
LD_LIBRARY_PATH = $ORACLE_HOME/lib32:$LD_LIBRARY_PATH; export LD_LIBRARY_PATH
注释:
ORACLE_HOME变量是产品根目录,就是有很多文件的上一级;
PATH中第一个/usr/ccs/bin是我用的make路径,这样每次就不用绝对地址了,直接make就行了。
$ORACLE_HOME/bin:$PATH路径下包含oracle提供的可执行文件。
LD_LIBRARY_PATH=$ORACLE_HOME/lib32为后面的cpp对应执行文件提供dll。
这里多提一下lib和lib32的区别吧,在oracle9i还是10g或更新的oracle,lib32表示的是32位的环境,而lib表示的是64位的环境。所以根据个人情况改写吧,对于makefile也是这样的。
setenv.sh的使用:
setenv.sh是一个shell脚本,可以手动执行./setenv.sh,这样你就能享受这些环境变量了,也可以自动执行,关于怎样自动执行建议看看.profile等文件相关内容,(本人喜欢bash环境,每次运行bash时会自动依次执行.bash_profile、.bashrc,所以在.bashrc中加入/setenv.sh即可。
bashrc内容是:
注意看最后一行指明了要运行setenv.sh,这样就不用手动执行了
# .bashrc
# Source global definitions
if [ -f /etc/bashrc ]; then
. /etc/bashrc
fi
#open core file
ulimit -S -c unlimited > /dev/null 2>&1
#time zone
# User specific aliases and functions
. ./zxliu/setenv.sh
2、Makefile的编写
在开始调用occi之前,首先需要在helloworld工作目录写一份Makefile文件,起名为makefile均可,make命令首先寻找Makefile,若不存在则会寻找makefile。
这时也要确认能否执行make命令,如果显示找不到,需要使用绝对地址执行make,如/usr/ccs/bin/make,默认unix均有make执行文件。
该Makefile内容如下:
###########################################
#Makefile for the OCCI demo programs
###########################################
#ORACLE_HOME变量指明unix上的oracle产品路径
ORACLE_HOME=/opt/app/ora10g/product/10.2.0
#ORACLE_INCLUDES变量指明产品路径下的各种include文件$()表示取值,注明这些文件对于后面cpp编译中include occi头文件很重要
ORACLE_INCLUDES=-I$(ORACLE_HOME)/rdbms/demo \
-I$(ORACLE_HOME)/rdbms/public \
-I$(ORACLE_HOME)/plsql/public \
-I$(ORACLE_HOME)/network/public \
-I$(ORACLE_HOME)/precomp/public
#ORACLE_LIBS变量指明,链接库,编译程序的时候很重要,而INC和LIB是连接程序时候需要的。-I表示引入的是头文件,-L表示引入的是动态链接库,-l表示在-L中连接的文件如clntsh.dll文件和occi.dll文件。所以-l必须和-L配合使用。
ORACLE_LIBS=-L$(ORACLE_HOME)/lib32 -L$(ORACLE_HOME)/rdbms/lib32
INC=$(ORACLE_INCLUDES)
LIB=$(ORACLE_LIBS) -lclntsh -locci
#为方便取下面三个变量,目标为helloworld,源文件是helloworld.cpp,编译后文件helloworld.o
PRG=helloworld
SRC=../../helloworld.cpp
OBJ=helloworld.o
#下面是常规的makefile内容,$@表示依次取目标执行,这里只有helloworld一个目标。实际等价于
#CC -o helloworld helloworld.o 不过加入了include和lib文件。而helloworld.o需要后续完成
$(PRG):$(OBJ)
@echo "begin link......"
CC $(INC) $(LIB) -o $@ $(OBJ)
#helloworld目标依赖helloworld.o生成,所以该句就是编译.c生成.o文件。只不过加入了include和lib文件
$(OBJ):$(SRC)
@echo "begin compile......"
CC $(INC) $(ORACLE_LIBS) -c $(SRC)
#后面的内容不是make的内容了,而是make clean内容。比如想重新make之前,清除.o等文件,执行make clean语句
#.PRNOY语句表明 clean关键词是个伪目标。make不自动执行。
.PRONY:clean
clean:
@echo "Removing linked and compiled files......"
rm -f $(OBJ) $(PRG)
写到这里,Makefile写完了,至于是否正确需要实际验证,因为每个人的oracle安装的不一样,所以里面的变量内容需要酌情更改,按照我说的更改即可。
验证方法很简单,执行make命令(或绝对路径用make),看是否能够编译.cpp并生成.o及最后的目标文件。一步一步检查看哪里存在问题。问题常常是oracle路径的问题要设置好。其实路径无非是编译需要的和链接需要的include及dll文件而已。所以根据这个思想去你的oracle目录下去找他们吧。 Makefile很关键,没写好的留言讨论。
验证代码如下:#include <iostream> #include <occi.h> using namespace std; using namespace oracle::occi; main() { Environment *env=Environment::createEnvironment(); cout<<"success"<<endl; }
注:编译好了,执行一下看是否输出success#include <iostream>
#include <occi.h>
using namespace std;
using namespace oracle::occi;
main()
{
Environment *env=Environment::createEnvironment();//create succ
string name = "name";
string pwd = "pwd";
string dbname = "DBDEMO";
try
{
Connection *conn=env->createConnection(name,pwd,dbname);
cout<<"conn succ!"<<endl;
env->terminateConnection(conn);
}
catch(SQLException e)
{
cout<<e.what()<<endl;
}
Environment::terminateEnvironment(env);
cout<<"end!"<<endl;
}
语句都能理解吧,就是建立链接,值得注意的是用户名和密码,以及DBDEMO名字,是unix配置的服务名,而不是远程oracle服务器的全局数据库名。本cpp是通过unix的network文件夹连接远程数据库服务器的。修改数据库内容就自己去学吧。还很多路要走。
ok,make、./helloworld 看看结果吧。