[LuaとC++の連携] Lua C APIを使って C/C++とLuaを連携させる方法

naohiro19
記事: 256
登録日時: 15年前
住所: 愛知県

[LuaとC++の連携] Lua C APIを使って C/C++とLuaを連携させる方法

投稿記事 by naohiro19 » 7年前

http://dixq.net/forum/blog.php?u=79&b=6869 この記事を書きましたが、純粋な Lua C APIを使って以下のようにグローバル変数の設定・取得、C言語関数の呼び出しをやってみたいと思います。
Lua C APIは第1引数に lua_State のポインターを渡す必要があります。Luaはエラーがなければ LUA_OK(=0)を返します。

[hr]
Luaからグローバル変数の値を取得

CODE:

w = 100
こういう Luaのグローバル変数がある場合は
  1. lua_getglobal関数でLuaの変数名を指定
  2. lua_toXXXの関数で実際に値を取り出す。
  3. スタックが残ったままになっているので lua_popでスタックを空っぽにする

実際のコード例は以下のようになります。

CODE:

#include 
#include 
#include "PrintStack.h"

int main()
{
   
    lua_State *L = luaL_newstate();
    luaL_openlibs(L);
    
    if (luaL_dofile(L, "sample.lua")  != LUA_OK) {
        printf("error:%s\n", lua_tostring(L, -1));
        lua_close(L);
        return -1;
    }
    
    lua_getglobal(L, "w");
    int w = lua_tointeger(L, -1);
    lua_pop(L, 1);
    printf("w = %d\n", w);
    lua_close(L); 
}
[hr]
こんどは C/C++から Luaにグローバル変数を登録してそれを Luaで表示させるとうことをやってみましょう。
グローバル変数の取得は lua_getglobal→lua_tonumberという順番ですが、設定する場合は値をlua_pushXXXで値をプッシュしてからlua_setglobalを呼び出します。

CODE:

#include 
#include 
#include "PrintStack.h"

int main()
{
   
    lua_State *L = luaL_newstate();
    luaL_openlibs(L);

    constexpr int MAX_SHOP_ITEMS = 5;
    lua_pushnumber(L, MAX_SHOP_ITEMS);
    lua_setglobal(L, "MAX_SHOP_ITEMS");
    
    
    if (luaL_dofile(L, "sample.lua")  != LUA_OK) {
        printf("error:%s\n", lua_tostring(L, -1));
        lua_close(L);
        return -1;
    }
    
    lua_close(L); 
}
上記のMAX_SHOP_ITEMSをLuaから使うには以下のように書けば利用ができます。

CODE:

print(MAX_SHOP_ITEMS) -- 5
[hr]
続いて C/C++から Luaの関数を呼ぶ例です。

CODE:

function add(x, y)
	return x + y
end
Luaで定義したadd関数を呼び出すには
  1. lua_getglobal関数を使って add関数をスタックに積む
  2. lua_pushXXXで引数に渡す
  3. lua_pcallを使ってLuaの関数を呼び出す
  4. lua_toXXXXで引数を取得す
という手順になります。

以下がC/C++のプログラムです。

CODE:

#include 
#include 
#include "PrintStack.h"

int main()
{
   
    // Luaの初期化
    lua_State *L = luaL_newstate();
    luaL_openlibs(L);
    
    // ファイルを読み込む
    if (luaL_dofile(L, "sample.lua")  != LUA_OK) {
        printf("error:%s\n", lua_tostring(L, -1));
        lua_close(L);
        return -1;
    }

    // add 関数を積む
    lua_getglobal(L, "add");

    // 引数は2個
    lua_pushinteger(L, 10);
    lua_pushinteger(L, 20);

    // Luaの関数を呼ぶ(引数:2個、戻り値:1個)
    if (lua_pcall(L, 2, 1, 0) != LUA_OK) {
        printf("error:%s\n", lua_tostring(L, -1));
        lua_close(L);
        return -1;
    }
    
    // 結果を表示
    printf("%d\n", lua_tointeger(L, -1));
    

    lua_close(L); 
    
}
[hr]
Luaから二つの引数を取りC言語の関数を呼び出して4つ返す関数です。以下のポイントがあります。
  1. LuaからC言語の関数を実行するには int型を戻り値として、引数としてlua_State構造体のポインターにする
  2. Luaのスタックから lua_toXXX関数を使って引数を取得
  3. 引数をスタックを lua_settop(L, 0); として空っぽにする
  4. 目的の関数を実行
  5. 結果を Luaのスタックにプッシュする
  6. return 文は戻り値の数を指定する

CODE:

#include 
#include 

int add_c(int x, int y) {
    return x + y;
}

int sub_c(int x, int y) {
    return x - y;
}

int mul_c(int x, int y) {
    return x * y;
}

int div_c(int x, int y) {
    return x / y;
}

int multiply(lua_State* L) {
    int x = lua_tointeger(L, 1);
    int y = lua_tointeger(L, 2);
    lua_settop(L, 0);

    int add_ret = add_c(x, y);
    int sub_ret = sub_c(x, y);
    int mul_ret = mul_c(x, y);
    int div_ret = div_c(x, y);

    lua_pushinteger(L, add_ret);
    lua_pushinteger(L, sub_ret);
    lua_pushinteger(L, mul_ret);
    lua_pushinteger(L, div_ret);
    return 4;
}


int main()
{
    lua_State *L = luaL_newstate();
    luaL_openlibs(L);

    lua_register(L, "multiply", multiply);

    if (luaL_dofile(L, "sample.lua") != LUA_OK) {
        printf("error:%s\n", lua_tostring(L, -1));
        lua_close(L);
        return 0;
    }

    lua_close(L);   
}
上記のadd_c/sub_c/mul_c/div_c関数をLuaから呼び出すには以下のように書きます。

CODE:


a, b, c, d = multiply(10, 9)

print(a)
print(b)
print(c)
print(d)
最後に編集したユーザー naohiro19 on 2017年12月24日(日) 00:34 [ 編集 2 回目 ]

コメントはまだありません。