C++でPython3を呼び出してSqliteデータベースにアクセスする

1.SqliteEngine.py

import sqlite3 #モジュールをインポート

class SqliteEngine:
def __init__(self,db_name):
self.db_name = db_name
try:
self.conn = sqlite3.connect(db_name)#データベースに接続する
self.cur = self.conn.cursor()
print(“db:" + db_name + “open succeed!")
except Exception as err:
print(str(err))

def close(self):
try:
self.conn.close()
print(“close db")
except Exception as err:
print(str(err))

def query(self,sql):
try:
self.cur = self.conn.cursor()
self.cur.execute(sql)
print('['+sql+’]’ + “success")
return self.get_recodeset(self.cur)
except Exception as err:
print(str(err))
return None

def exec(self,sql):
try:
self.cur = self.conn.cursor()
self.cur.execute(sql)
self.conn.commit()
print('['+sql+’]’ + “success")
return 0
except Exception as err:
self.conn.rollback()
print(str(err))
return -1

def get_recodeset(self,cur):
recodeset = cur.fetchall()#レコードセットを取得
field = [field_name[0] for field_name in cur.description]#レコードセットのフィールドリスト

ret_list=[]#空リスト
for each_item in recodeset:
recode_dic={};#空の辞典
col_index=0
for each_col in each_item:

key = str(field[col_index]).encode(“shift-jis","ignore")
value = str(each_col).encode(“shift-jis","ignore")
recode_dic[key] = value
col_index+=1
ret_list.append(recode_dic)
return tuple(ret_list)
"’
def strPrint(s):
print(s)
return str(s).encode(“shift-jis")
"’

2.SqliteEngine.h
#ifndef SQLITEENGINE_H_
#define SQLITEENGINE_H_

#include <Python.h>
#include <string>
#include <vector>
#include <map>

using namespace std;

typedef vector<map<string,string> > Recodeset;//レコードのクエリの結果セット
typedef map<string,string> Recode;//単一レコード
typedef Recodeset::iterator PRecodeset;
typedef Recode::iterator PRecode;

class SqliteEngine
{
public:
SqliteEngine(string py);
~SqliteEngine(void);

static bool initPython();
static bool unInitPython();

bool open(string db_name);

void close();

int query(string sql,Recodeset& Rec);

int execute(string sql);

private:
PyObject* m_pModule;
PyObject* m_pPySqlite;
string m_Py_module_name;
};

#endif //SQLITEENGINE_H_

3.SqliteEngine.cpp
#include “SqliteEngine.h"

SqliteEngine::SqliteEngine(string py)
:m_pModule(NULL),
m_pPySqlite(NULL),
m_Py_module_name(py)
{
}

SqliteEngine::~SqliteEngine()
{
SqliteEngine::unInitPython();
m_pModule = NULL;
m_pPySqlite = NULL;
}

bool SqliteEngine::initPython()
{
Py_Initialize();
//Py_IsInitializedは0を戻す、Python環境を初期化する
return Py_IsInitialized()?true:false;
}
bool SqliteEngine::unInitPython()
{
Py_Finalize();
return Py_IsInitialized()?false:true;
}

bool SqliteEngine::open(string db_name)
{
//Pythonモジュールのインポート
m_pModule = PyImport_ImportModule(m_Py_module_name.c_str());//*.py,サフィックス無し
if (!m_pModule)
{
printf(“Can not open python file!\n");
return false;
}

//SqliteEngineクラスを取得
PyObject* pClass = PyObject_GetAttrString(m_pModule,"SqliteEngine");
if (!pClass)
{
printf(“Can not find class [SqliteEng]!\n");
return false;
}

//パラメータ
PyObject* pArg = PyTuple_New(1);
PyTuple_SetItem(pArg, 0, Py_BuildValue(“s",db_name.c_str()));

//SqliteEngineの例を構成
m_pPySqlite= PyEval_CallObject(pClass,pArg);
if (!m_pPySqlite)
{
printf(“Can not find instance!\n");
return false;
}
return true;
}

void SqliteEngine::close()
{
if(!m_pPySqlite)
{
return;
}
PyObject_CallMethod(m_pPySqlite,"close",NULL);
}

int SqliteEngine::execute(string sql)
{
if(!m_pPySqlite)
{
return -1;
}
int nRet = 0;
PyObject* py_ret = PyObject_CallMethod(m_pPySqlite,"exec","s",sql);
PyArg_Parse(py_ret,"i",&nRet);

return nRet;
}

int SqliteEngine::query(string sql,Recodeset& Rec)
{
if(!m_pPySqlite)
{
return -1;
}

PyObject* tuple = PyObject_CallMethod(m_pPySqlite, “query", “s",sql.c_str() );
if(!tuple)
{
return -1;
}

Py_ssize_t tuple_size = PyTuple_Size(tuple);
PyObject* dic = NULL;
Py_ssize_t dic_pos = 0;
PyObject *_key = NULL;
PyObject *_value = NULL;
const char* c_sKey =NULL;
const char* c_sVal = NULL;
if( tuple && tuple_size>0 )
{

for(Py_ssize_t i=0;i<tuple_size;i++)
{
dic = PyTuple_GetItem(tuple,i);
dic_pos = 0;

//辞書をトラバーサル
Recode _map;
while ( PyDict_Next(dic,&dic_pos,&_key,&_value) )
{
c_sKey = PyBytes_AsString(_key);
c_sVal = PyBytes_AsString(_value);

if(c_sKey)
{
_map.insert(make_pair(c_sKey,c_sVal));
}
}
Rec.push_back(_map);
}
}
return Rec.size();
}

Development

Posted by arkgame