作業と思いつきの記録

日々忘れがちになるので作業の記録や、思いつきなどを残していきます

sol2: SQLite3を扱うC関数を呼び出して結果をコンテナvectorで返す

sol2を使う練習として、LuaからSQLite3を操作するプログラムを作成した。

実装の概要

  1. SQLite3を操作するユーザデータとして、クラスまたは構造体で実装する
  2. 戻り値を格納するユーザデータを実装する
  3. ユーザデータを登録する
  4. Luaスクリプトを実行する

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); 
        }
    );

一応の実行結果 f:id:diCE-K:20190911103752p:plain

参考