FPGA開発日記

カテゴリ別記事インデックス https://msyksphinz.github.io/github_pages , English Version https://fpgadevdiary.hatenadiary.com/

LuaとC言語への組み込みの勉強(1)

ISSを外部から操作するための、スクリプト言語を組込みたくて、Luaについて調査してみた。

第 5 回: Lua を組み込み用の言語として利用する方法 (関数編) — WTOPIA v1.0 documentation

Ubuntuで挑戦したのだが、インストールしたパッケージは以下。

sudo aptitude install lua5.2 liblua5.2-dev

最初コンパイル出来なくて大分いろいろ試したが、C++コンパイルするときはlua.hppをインクルードしないといけないらしい。

$ cat lua_in_c.cpp
#include <stdio.h>

#include <lua5.2/lua.hpp>
#include <lua5.2/lualib.h>
#include <lua5.2/lauxlib.h>

int main(int argc, char *argv[]){

    const char *fn = "hello.lua";
    // Lua の言語エンジンを初期化
    lua_State *lua = luaL_newstate();

    // Lua のライブラリを使えるようにする
    luaL_openlibs(lua);

    // Lua のスクリプトを読み込む
    printf("%d\n", luaL_dofile(lua, fn));

    return 0;
}

$ cat hello.lua
-- hello.lua
-- print 関数は自動的に "\n" を入れることを忘れない
print("Hello Lua World")
print("你好 Lua")
print("こんにちは Lua")

これでコンパイルして、実行してみる。

g++ -o call_from_lua call_from_lua.cpp -llua5.2
./lua_in_c
Hello Lua World
你好 Lua
こんにちは Lua
0

おお、動いた。

次にやりたいのは、Luaスクリプト側からC++の関数を呼び出すこと。

cat call_from_lua.cpp
/*
  for_lua.cpp
*/

#include <stdio.h>

#include <lua5.2/lua.hpp>
#include <lua5.2/lualib.h>
#include <lua5.2/lauxlib.h>

/* 足し算を行う関数 */
int c_add(lua_State *L){
    // 引数を得る
    int a1 = lua_tointeger(L, 1); // 第 1 引数を得る
    int a2 = lua_tointeger(L, 2); // 第 2 引数を得る
    // 計算
    int r = a1 + a2;
    printf("[%d + %d]\n", a1, a2);
    // 結果をスタックに戻す
    lua_pushinteger(L, r);
    return 1; // 戻り値の数を返す
}

/* エラーを表示するための関数 */
void show_error(lua_State *L){
    const char *err = lua_tostring(L, -1);
    printf("ERROR: %s\n", err);
}

/* メイン */
int main(int argc, char *argv[]){
    lua_State *L = luaL_newstate();
    luaL_openlibs(L); // Lua のライブラリを使えるようにする

    // Lua に関数を登録する
    lua_register(L, "c_add", c_add);

    // Lua のスクリプトを読み込む
    if (luaL_loadfile(L, "call_c_func.lua") || lua_pcall(L, 0, 0, 0) ){
        printf("call_c_func.lua が読めなかった\n");
        show_error(L);
        return -1;
    }

    lua_close(L); // 閉じる
    return 0;
}

上記のソースを呼び出す側はこのようにした。

cat call_c_func.lua
print (c_add(10, 20))

これでコンパイルして実行する。

g++ -o call_from_lua call_from_lua.cpp -llua5.2
./call_from_lua
[10 + 20]
30

ちゃんと動作した!