C言語のプログラムにLuaインタプリタを組み込む

ここではWindows/VC++環境で、C言語のプログラムにLuaインタプリタを組み込んでみる。

Luaライブラリのダウンロード

  • Lua Binariesより、Windows用のライブラリをダウンロードする。
  • 32ビット版ならlua-x.x.x_Win32_dllw4_lib.zip
  • 64ビット版ならlua-x.x.x_Win64_dllw4_lib.zip

VC++のプロジェクトにファイルを配置

  • VC++でプロジェクトを作成する。
  • 上記zipファイルを解凍した中身をプロジェクトディレクトリに配置する。

プロジェクトのプロパティの設定

  • C/C++>全般>追加のインクルードディレクトリに $(ProjectDir)\include を追加
  • リンカー>全般>追加のライブラリディレクトリに $(ProjectDir) を追加
  • リンカー>入力>追加の依存ファイルに liblua53.a を追加

Luaスクリプト文字列を実行

#include <stdio.h>
#include "lua.hpp"

int main(void)
{
    // Luaの初期化
    lua_State* L = luaL_newstate();
    // Luaの標準ライブラリを読み込み
    luaL_openlibs(L);
    // Luaスクリプト文字列を実行
    luaL_dostring(L, "print('hello, world!')");
    // Luaを終了
    lua_close(L);
    return 0;
}

Luaスクリプトファイルを実行

下記Luaスクリプトファイルを作成してプロジェクトディレクトリに配置する。

-- 人口のテーブル ※配列も構造体もなくすべてテーブル
cities = {
    {city = "Osaka",    pop = 2725006 },
    {city = "Tokyo",    pop = 9396595 },
    {city = "Nagoya",   pop = 2320361 },
    {city = "Yokohama", pop = 3741765 }
}

-- 一覧表示
for i, v in ipairs(cities) do print(v.city) end

-- ソート ※無名関数を引数にできることに注目
table.sort(cities, function(a, b) return (a.pop > b.pop) end)

-- ふたたび一覧表示
print("---");
for i, v in ipairs(cities) do print(v.city) end

これを下記C言語プログラムから実行する。

#include <stdio.h>
#include "lua.hpp"

int main(void)
{
    // Luaの初期化
    lua_State* L = luaL_newstate();
    // Luaの標準ライブラリを読み込み
    luaL_openlibs(L);
    // Luaスクリプトファイルを実行
    luaL_dofile(L, "test.lua");
    // Luaを終了
    lua_close(L);
    
    return 0;
}

LuaからC言語の関数を呼ぶ出す

#include <stdio.h>
#include "lua.hpp"

// Cの関数: Luaからは add(x, y) と呼び出す
int add(lua_State *L)
{
	// 引数をLuaから取得
    int const x = (int)lua_tonumber(L, 1);
    int const y = (int)lua_tonumber(L, 2);
    // Luaのスタックのクリア
    lua_settop(L, 0);
    
    // 処理の中身
    int const ret = x + y;
    
    // 戻り値をLuaのスタックにプッシュ
    lua_pushnumber(L, ret);
    return 1;
}

int main(void)
{
    // Luaの初期化
    lua_State *L = luaL_newstate();
    // Luaの標準ライブラリを読み込み
    luaL_openlibs(L);
    // LuaにCの関数を登録
    lua_register(L, "add", add);
    // Luaスクリプトを実行
    luaL_dostring(L, "print(add(5, 3))");
    // Luaを終了
    lua_close(L);
    
    return 0;
}

C言語からLuaの関数を呼び出す

#include <stdio.h>
#include "lua.hpp"

int main(void)
{
    // Luaの初期化
    lua_State *L = luaL_newstate();
    // Luaスクリプトを実行 (Luaの関数を定義)
    luaL_dostring(L, "function add(x, y) return x + y end");
    // Luaのスタックに、定義した関数を積む。
    lua_getglobal(L, "add"); 
    // Luaのスタックに引数をプッシュ
    lua_pushinteger(L, 5);
    lua_pushinteger(L, 3);
    
    // Luaの関数を呼び出す (引数は2個、戻り値は1個)
    lua_call(L, 2, 1); 
    
    // 結果を表示
    printf("Result: %d\n", lua_tointeger(L, -1));
    // Luaを終了
    lua_close(L);
    
    return 0;
}