本來公司的項目是在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