C/C++操作Oracle数据库的方式核心有两种:C的OCI与C++的OCCI,OCCI的语法近于 JDBC,简单易学,但OCI接口复杂,难以学习、理解和使用,因此Oracle提出了折中方案:Pro*C,在C语言文件里嵌入SQL语句,通过proc预编译产生包含OCI函数的C文件,但另外的麻烦又来了,预编译文件.pc,由于嵌入了SQL语句,并不符合C的语法,IDE会产生警告,自然,如果你习惯于使用vi来编辑,则令当别论了。如果在C源文件中直接使用OCCI的方法,使用C++编译器来编译所有的C文件,也是一种简化问题的方法,但将大量C文件使用C++编译器编译让人感觉不是那么痛快。
如果能封装OCCI对数据库的操作,并生成C语言的动态库或静态库,那就可以继续使用C编译器来编译其他的源文件了,最终动态链接或通过连接器静态链接到一起就行了。
一、 C++的OCCI操作数据库
要用C封装OCCI,首先是要知道如果用C++通过OCCI来操作数据库
/*
* occi.h
*
* Created on: Apr 22, 2009
* Author: hanchen
*/
#ifndef OCCI_H_
#define OCCI_H_
#include <occi.h>
using namespace std;
using namespace oracle::occi;
class OcciDemo {
private:
Environment *env;
Connection *conn;
public:
OcciDemo(string user, string passwd, string dbname);
~OcciDemo();
void displayTable();
};
#endif /* OCCI_H_ */
/*
* occi.cpp
*
* Created on: Apr 22, 2009
* Author: hanchen
*/
#include <iostream>
#include <algorithm>
#include "occi.h"
OcciDemo::OcciDemo(string user, string passwd, string dbname) {
env = Environment::createEnvironment(Environment::OBJECT);
conn = env->createConnection(user, passwd, dbname);
}
OcciDemo::~OcciDemo() {
cout << "delete OcciDemo" << endl;
env->terminateConnection(conn);
Environment::terminateEnvironment(env);
}
void OcciDemo::displayTable() {
Statement *stmt = conn->createStatement();
ResultSet *rs = stmt->executeQuery("select id from usr");
try {
while (rs->next()) {
cout << rs->getInt(1) << endl;
}
} catch (SQLException se) {
cout << "Error number: " << se.getErrorCode() << endl;
cout << se.getMessage() << endl;
}
}
/*
* t_occi.cpp
*
* Created on: Apr 22, 2009
* Author: hanchen
*/
#include "occi.h"
int main(void) {
OcciDemo *occi = new OcciDemo("hanchen", "123456", "orcl");
occi->displayTable();
delete (occi);
return 0;
}
二、网上关于C++导出成为C的so文件例子很多,照葫芦画瓢即可。自然,实际上并不需要使用occi.cpp来操作,直接在C源文件里操作OCCI导出即可。
/*
* e_occi.h
*
* Created on: Apr 22, 2009
* Author: hanchen
*/
#ifndef E_OCCI_H_
#define E_OCCI_H_
#ifdef _cplusplus
extern "C"
{
#endif
void eocci_test();
#ifdef _cplusplus
}
#endif
#endif /* E_OCCI_H_ */
/*
* e_occi.cpp
*
* Created on: Apr 22, 2009
* Author: hanchen
*/
#ifndef _cplusplus
#define _cplusplus
#endif
#include "occi.h"
#include "e_occi.h"
void eocci_test() {
OcciDemo occi("hanchen", "123456", "orcl");
occi.displayTable();
}
/*
* t_e_occi_so.c
*
* Created on: Apr 22, 2009
* Author: hanchen
*/
#include <stdio.h>
#include <dlfcn.h>
#include "e_occi.h"
int main(void) {
void (*df)();
void *hl;
hl = dlopen("./e_occi.so", RTLD_LAZY);
df = dlsym(hl, "eocci_test");
(*df)();
dlclose(hl);
return 0;
}
三、动态链接虽然简单,但操作麻烦,如果程序员自己能控制代码的话,做静态链接则是一种更好的选择
/*
* t_e_occi_a.c
*
* Created on: Apr 22, 2009
* Author: hanchen
*/
#include <stdio.h>
#include <dlfcn.h>
#include "e_occi.h"
int main(void) {
eocci_test();
return 0;
}
四、makefile,想必您看到这里已经很厌烦了,光看代码不一定能实际运用,最后是三个单元的makefile集合,什么,你说你不知道makefile是什么东西?。。。如果你是windows用户,并且在windows下开发C程序的话,那么您没必要看下去了,如果你是linux C程序员,那我建议你还是先学习下linux C开发的基础。。。废话少说。。。看文件
ORACLE_HOME=/opt/oracle/ora11
TARGET=t_occi t_e_occi_so t_e_occi_a
all:$(TARGET)
occi.o:occi.cpp
g++ -o $@ $^ -c -I$(ORACLE_HOME)/rdbms/public
t_occi.o:t_occi.cpp
g++ -o $@ $^ -c -I$(ORACLE_HOME)/rdbms/public
e_occi.o:e_occi.cpp
g++ -o $@ $^ -c -I$(ORACLE_HOME)/rdbms/public
e_occi.so:e_occi.o occi.o
g++ -o $@ $^ -shared
t_e_occi_a.o:t_e_occi_a.c
gcc -o $@ $^ -c
t_occi:t_occi.o occi.o
g++ -o $@ $^ -L$(ORACLE_HOME)/lib -locci -lclntsh
t_e_occi_so:e_occi.so
gcc -o $@ t_e_occi_so.c -ldl -L$(ORACLE_HOME)/lib -locci -lclntsh
t_e_occi_a:t_e_occi_a.o e_occi.o occi.o
gcc -o $@ $^ -L$(ORACLE_HOME)/lib -locci -lclntsh
clean:
rm -rf *.o *.so
rm -rf $(TARGET)
makefile写的很复杂,一会是gcc,一会儿是g++,您耐心慢慢读,如果你无法编译出C++版本通过OCCI操作数据的程序,那么建议您读读另外一篇文章 linux下使用occi链接oracle11
没有评论:
发表评论