本来公司的项目是在linux下处理的. 由于近期人员调动. 需要增加几个新人. 为了让不熟悉linux开发环境的新人能够尽快上手使用公司的基础类库, 所以我承担了搭建windows下的开发环境搭建工作
其中第一项就是将公司使用的基于oci的封装ocicpp编译出一个mingw32的版本
1. 必要工具
Instant Client Downloads for Microsoft Windows
http://www.oracle.com/technology/software/tech/oci/instantclient/htdocs/winsoft.html
oracle instant Client
mingw32
自行搜索下载地址, 本人使用3.42
gcc的win32版本
pexports for mingw32
自行搜索下载地址
将c的dll导出为def的工具, 如果你的mingw没有自带. 请自行下载. 并放到path可以找到的地方, 不支持c++的dll.
以上工具自行安装
instantclient解压到D:\Develop\Cplus\instantclient_11_1\
mingw32安装到D:\Develop\Cplus\MinGW\
pexports.exe解压到D:\Develop\Cplus\MinGW\bin\
2. 生成能被mingw32调用的oci lib
由于oracle 官方的oci sdk并无提供可供mingw link的包. 所以我们需要手工根据dll做一个
使用dll产生mingw32的lib
导出def
D:\Develop\Cplus\instantclient_11_1\sdk\lib>pexports oci.dll > oci.def
生成lib
D:\Develop\Cplus\instantclient_11_1\sdk\lib>dlltool --dllname oci.dll --def oci.def --output-lib liboci.a
这样我们就有了一个可以mingw32 link的 liboci.a了
3.配置oracle instant Client
只需要3个环境变量
TNS_ADMIN=D:\Develop\Cplus\instantclient_11_1
NLS_LANG=SIMPLIFIED CHINESE_CHINA.ZHS16GBK
PATH=%PATH%;%TNS_ADMIN%\
4.编译执行测试程序.
保密协议导致我无法公开ocicpp的源码.
但是可以贴基于ocicpp的测试程序
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include "ocicpp/ocicpp.h"
#include "ocicpp/db.h"
using namespace OCICPP;
bool InsertDataBySQL(Connection* pConn)
{
Cursor cursor;
string strSQL;
strSQL = "INSERT INTO testOCICPP (TestId, UserName, PassWord, Address ) VALUES(13, 'xxxxx', '!@#$1234', 'xxxxx')";
try {
pConn->execQuery(strSQL, cursor);
cursor.drop();
pConn->transCommit();
}
catch (OraError err) {
cout << "InsertDataBySQL Exception: " << err.message << endl;
return false;
}
return true;
}
bool UpdateDataBySQL(Connection* pConn)
{
Cursor cursor;
string strSQL;
strSQL = "UPDATE testOCICPP SET PassWord = '&*()7890'";
try {
pConn->execQuery(strSQL, cursor);
cursor.drop();
pConn->transCommit();
}
catch (OraError err) {
cout << "UpdateDataBySQL Exception: " << err.message << endl;
return false;
}
return true;
}
bool DelRecordBySQL(Connection* pConn)
{
Cursor cursor;
string strSQL;
strSQL = "DELETE FROM testOCICPP";
try {
pConn->execQuery(strSQL, cursor);
cursor.drop();
pConn->transCommit();
}
catch (OraError err) {
cout << "DelRecordBySQL Exception: " << err.message << endl;
return false;
}
return true;
}
bool FetchDataBySQL(Connection* pConn)
{
Cursor cursor;
string strSQL;
strSQL = "SELECT MEMBERID,MOBILE,PASSWD,ADDRESS FROM tblmember where rownum<20";
try {
pConn->execQuery(strSQL, cursor);
while (cursor.fetch()) {
cout << ".......... Record .........." << endl;
cout << "TestId: " << cursor.getInt("MEMBERID") << endl;
cout << "UserName: " << cursor.getStr("MOBILE") << endl;
cout << "PassWord: " << cursor.getStr("PASSWD") << endl;
cout << "Address: " << cursor.getStr("ADDRESS") << endl;
}
cursor.drop();
pConn->transCommit();
}
catch (OraError err) {
cout << "FetchDataBySQL Exception: " << err.message << endl;
return false;
}
return true;
}
bool InsertDataByProcedure(Connection* pConn)
{
Cursor cursor;
string strSQL;
int iRetCode=0;
strSQL = "BEGIN testProcInsert(13, 'xxxxx', '!@#$1234', 'xxxxx', :RetCode); END;";
try {
pConn->prepare(strSQL, cursor);
cursor.bind(":RetCode", iRetCode);
cursor.execute(); cursor.drop();
}
catch (OraError err) {
cout << "InsertDataBySQL Exception: " << err.message << endl;
return false;
}
cout << "InsertDataByProcedure RetCode: " << iRetCode << endl;
return true;
}
bool UpdateDataByProcedure(Connection* pConn)
{
return false;
}
bool DelRecordByProcedure(Connection* pConn)
{
return false;
}
bool FetchDataByProcedure(Connection* pConn)
{
return false;
}
int StartRun(int p_iMode)
{
Connection dbConn;
OCICPP::db::init();
try{
OCICPP::db::connect("smsdb", "point", "point1234", dbConn);
switch(p_iMode)
{
case 1:
InsertDataBySQL(&dbConn);
break;
case 2:
UpdateDataBySQL(&dbConn);
break;
case 3:
DelRecordBySQL(&dbConn);
break;
case 4:
FetchDataBySQL(&dbConn);
break;
case 5:
InsertDataByProcedure(&dbConn);
break;
case 6:
UpdateDataByProcedure(&dbConn);
break;
case 7:
DelRecordByProcedure(&dbConn);
break;
case 8:
FetchDataByProcedure(&dbConn);
break;
default:
break;
}
} catch(OraError err) {
cout << "OraError Exception: " << err.message << endl;
}
return 0;
}
int main(int argc, char* argv[])
{
if (argc != 2)
{
cout << endl;
cout << "Please input run mode (1 - 6): " << endl;
cout << endl;
cout << " 1: InsertDataBySQL" << endl;
cout << " 2: UpdateDataBySQL" << endl;
cout << " 3: DelRecordBySQL" << endl;
cout << " 4: FetchDataBySQL" << endl;
cout << " 5: InsertDataByProcedure" << endl;
cout << " 6: UpdateDataByProcedure" << endl;
cout << " 7: DelRecordByProcedure" << endl;
cout << " 8: FetchDataByProcedure" << endl;
cout << endl;
exit(-1);
}
int iMode = atoi(argv[1]);
//pid_t iPid;
//iPid = fork();
//if (iPid == 0)
//{
StartRun(iMode);
exit(0);
//}
//else if (iPid < 0)
//{
// cout << "Fork Failure" << endl;
//}
//sleep(3);
cout << "................. Finish ................." << endl;
return 0;
}
/*****************************************************************
CREATE TABLE testOCICPP
(
TestId number(10, 0) DEFAULT 1 NOT NULL,
UserName varchar2(16) DEFAULT ' ' NOT NULL,
PassWord varchar2(16) DEFAULT ' ' NOT NULL,
Address varchar2(128) DEFAULT ' ' NOT NULL
)tablespace rism_db;
CREATE OR REPLACE PROCEDURE testProcInsert(
p_iTestId IN number, p_sUserName IN string, p_sPassWord IN string,
p_sAddress IN string, p_iRetCode OUT number)
IS
BEGIN
p_iRetCode := 0;
INSERT INTO testOCICPP(TestId, UserName, PassWord, Address)
VALUES(p_iTestId, p_sUserName, p_sPassWord, p_sAddress);
COMMIT;
EXCEPTION
WHEN OTHERS THEN
p_iRetCode := SQLCODE;
END;
/
*****************************************************************/
编译成ocicpp.exe
此时需要两个dll文件与ocicpp.exe在同一个目录
在oracle instant Client安装目录下找到oraociei11.dll oci.dll
根据版本不同. oraociei11.dll这个文件名或许会有差异.
也可以将俩dll扔到system32目录下
本人服务器端为rhel 3.4 ,数据库环境为9.2.04
客户端环境为windows mingw32-gcc3.42