sol2: SQLite3を扱うC関数を呼び出して結果をコンテナvectorで返す
sol2を使う練習として、LuaからSQLite3を操作するプログラムを作成した。
実装の概要
SQLite3を操作するクラス
今回は、sqlite3.cをプロジェクトに取り込む方法で使う。
一部抜粋:
class CLuaSQLite { private: sqlite3* _db; sqlite3_stmt* _stmt; public: CLuaSQLite(); void debug(const std::string& msg); int open(const std::string& filename); void close(); void exec(const std::string& query); ResultData select(const std::string& query); };
上記のクラスをユーザデータとして登録する
lua.new_usertype<CLuaSQLite>("sqlite3", sol::constructors<CLuaSQLite()>(), "debugPrint", &CLuaSQLite::debug, // "open", &CLuaSQLite::open, "close", &CLuaSQLite::close, "exec", &CLuaSQLite::exec, "select", &CLuaSQLite::select );
Luaからの呼び出し
function runMain() local sq = sqlite3.new(); sq:debugPrint("runMain() from Lua"); -- SQLite3の操作をテストする local ret = sq:open("test.sqlite"); if ret == 1 then -- error print("データベースのオープンに失敗した"); end -- 書き込み sq:exec("create table personal(id, name, age);"); --[[ sq:exec("insert into personal values ('aaa', 'bbb', 99);"); --]] -- 読み込み local selStmt = "select * from personal;"; local selResult = sq:select(selStmt); -- 結果を出力してみる print("[Lua] 結果を出力してみる"); for i, v in pairs(selResult) do -- v : rowdata print("select......"..i); for ri, rv in pairs(v) do print(" rowdata......type: "..rv:getType()..", "..rv:getColName()); if (rv:getType() == 1) then print(" data: "..rv:getInteger()); elseif (rv:getType() == 3) then print(" data: "..rv:getText()); end end end sq:close(); sq:debugPrint("end."); end
戻り値をコンテナ: vectorで返す
ユーザデータとするクラスを作り、クラス内に戻り値にするvectorを定義する。 ネストも可能。
ソースコードの一部抜粋
struct ResultData { private: // 戻り値 std::vector<rowData> _record; public: ResultData(){} // row set void setRow(rowData rd){ _record.emplace_back(rd); } using value_type = decltype(_record)::value_type; using iterator = decltype(_record)::iterator; using size_type = decltype(_record)::size_type; iterator begin() { return iterator(_record.begin()); } iterator end() { return iterator(_record.end()); } size_type size() const noexcept { return _record.size(); } size_type max_size() const noexcept { return _record.max_size(); } void push_back(rowData value) { _record.push_back(value); } bool empty() const noexcept { return _record.empty(); } };
上記ユーザデータの登録
lua.new_usertype<ResultData>("result_data", sol::constructors<ResultData()>(), "iterable", [](ResultData& rd) { return sol::as_container(rd); } );
一応の実行結果