うたカモ技術ブログ

Lua C

Luaプログラミング    LuaスクリプトからC言語の関数を呼び出す方法

post: 

今回はLuaスクリプトからC言語関数を呼び出す方法について紹介します。

前回の記事「Luaプログラミング C言語ソフトウェアからLuaを呼び出す方法」ではLuaステートを使用してC言語からLuaスクリプトやその中の関数を呼び出す方法について紹介しました。

詳細としては、共有オブジェクト(ライブラリ)のliblua.soを利用して自作のC言語ソフトウェアにLuaインタプリタ(実行環境)を組み込むことで Luaスクリプトを読み込んで実行しました。

この時、実行環境のインスタンスとしてLuaステートというオブジェクトを扱いました。

今回は、このLuaステートの中にC言語関数のエントリを追加することでLuaスクリプトから特定のC言語関数を呼び出せるようにしてみます。

#実行環境OS
ubuntu 22.04 LTS 64bit
#Lua
Ver 5.4.7

前提条件:Luaライブラリ(liblua.so)のインストール

C言語からLuaスクリプトを実行するには、予め開発環境にLuaライブラリ(liblua.so)をインストールする必要があります。 以下にインストール方法について掲載します。これはLua公式サイトのダウンロードページに掲載されているものです。 まだインストールしていない方はここで実施しましょう。

user:~$ curl -L -R -O https://www.lua.org/ftp/lua-5.4.7.tar.gz
user:~$ tar zxf lua-5.4.7.tar.gz
user:~$ cd lua-5.4.7
user:~$ make all test
user:~$ sudo make install

このLuaライブラリは次節で紹介するC言語バイナリ用のLua実行環境(Luaステート)を構築するための実装です。 ライブラリを適切に使用することで、指定したLuaスクリプトやその中の関数を明示して実行することが可能になります。

sudo make installで/usr/local/libに共有オブジェクトのliblua.soが格納されます。 これでコンパイル時にgcc -o test test.c -llua -lm -ldlとすることで、C言語ソースのtest.cにliblua.so(-llua)をリンクすることができます。

※なお、5.4.4以降のどこかで数学系とダイナミックリンク系の共有オブジェクト(ライブラリ)のlibm.so(-lm)とlibdl.so(-ldl)もリンクしないといけなくなったようです。

それでは、次節から説明に入ります。

LuaスクリプトからC言語関数を呼び出す

「LuaスクリプトからC言語関数を呼び出す」にはLuaインタプリタを組み込んだC言語ソースコード側で C言語関数のエントリをLuaステート上にプリロードする必要があります。

C言語関数のプリロードはlua_register関数を実行することで実施します。

次はC言語関数のgreetとaddをLuaステート内にプリロードし、Luaスクリプト側で c_greet、c_addとして呼び出せるようにしたソースコード(test.c)です。

//test.c
#include <lauxlib.h>
#include <lua.h>
#include <lualib.h>
#include <stdio.h>
#include <stdlib.h>

int greet(lua_State *);
int add(lua_State *);

int main() {
    int status, result;
    lua_State *L;
    L = luaL_newstate();    //Luaステートの構築
    luaL_openlibs(L);         //Lua標準ライブラリの導入(インポート)

    lua_register(L, "c_greet", greet);
    lua_register(L, "c_add", add);

    status = luaL_dofile(L, "test.lua");     //Luaスクリプトをロードして実行

    if(status) {
        fprintf(stderr, "Couldn't load file: %s", lua_tostring(L, -1));
        return 1;
    }

    lua_close(L);   //Luaステートのクローズ

    return 0;
}

int greet(lua_State *L) {
    const char *str = lua_tostring(L, 1);
    printf("Hello!! %s!\n", str);
    return 0;
}

int add(lua_State *L) {
    int x = lua_tointeger(L, 1);
    int y = lua_tointeger(L, 2);
    lua_pushinteger(L, x + y);
    return 1; // returnの値で戻り値が1つ存在することを認識
}

上記のgreet関数とadd関数をそれぞれc_greet、c_addで呼び出して実行する Luaスクリプト(test.lua)は以下の通りです。

-- test.lua
io.write("Your Name: ")
local name = io.read()
c_greet(name)

io.write("x: ")
local x = io.read()
io.write("y: ")
local y = io.read()

local sum = c_add(x, y)

print(x .. ' + ' .. y .. ' = ' .. sum)

それではコンパイルして動作確認をします。

今回、私の環境ではホームディレクトリ直下にtest-luaというディレクトリを作り、そこに上記掲載のソースファイルを保存した上でtest.cをコンパイルしました。 このとき、Luaライブラリ(liblua.so)とリンクするために、-lluaを指定します。

kamo@kamo:~/test-lua$ ls
test.c test.lua
kamo@kamo:~/test-lua$ gcc -o test test.c -llua -lm -ldl

これでコンパイルが完了しました。さっそく実行してみます。

kamo@kamo:~/test-lua$ ./test
Your Name: utakamo
Hello!! utakamo!
x: 1
y: 2
1 + 2 = 3

このようにLuaスクリプトはC言語の連携が可能なスクリプト言語です。

用途に応じた使い方をすることでソフトウェアの拡張性が高まります。

参考文献

ガジェット記事も読む

Thunderboltとは何か? パソコン購入前に知っておきたいポイントを整理

Thunderboltとは何か? パソコン購入前に知っておきたいポイントを整理

Thunderboltとは何かを、パソコン購入を検討している人向けに整理します。Thunderbolt 4と5の違い、USB4との関係、製品ページで確認したいポイントをまとめています。

【初めてのスマートホーム】      ハブ・スマートリモコンと周辺デバイスの選び方

【初めてのスマートホーム】 ハブ・スマートリモコンと周辺デバイスの選び方

スマートホームデバイスを初めて選ぶ人向けに、中核となるハブ・スマートリモコン5製品と、照明・スマートロック・センサーなど追加端末10製品の役割と選び方を整理します。

ハンドヘルドゲーミングPCとは何か? 代表メーカーと製品を紹介

ハンドヘルドゲーミングPCとは何か? 代表メーカーと製品を紹介

ハンドヘルドゲーミングPCとは何かを整理し、Steam Deck OLED、ROG Xbox Ally X、Lenovo Legion Go、MSI Claw A1Mなど代表的なメーカー と製品

2026年版 家庭用プロジェクターの選び方 用途別おすすめモデル5選

2026年版 家庭用プロジェクターの選び方 用途別おすすめモデル5選

家庭用プロジェクターを初めて選ぶ人向けに、明るさ、解像度、投写距離、内蔵OS、設置方法を整理し、用途別に代表6機種を紹介します。

自宅で木材を削ってものづくり!家庭用CNC加工機おすすめ5選

自宅で木材を削ってものづくり!家庭用CNC加工機おすすめ5選

家庭用CNC加工機の仕組みと3Dプリンターとの違いを紹介します。GenmitsuとFoxAlienの5機種を、加工範囲・用途・設置条件から比較します。

暗号資産の秘密鍵・署名を管理するハードウェアウォレットとは?

暗号資産の秘密鍵・署名を管理するハードウェアウォレットとは?

取引所で暗号資産を持つ人の疑問から、クリプトウォレットの仕組みを整理します。取引所保管との違い、必要になりやすい人、売買・送金・店舗決済の関係を紹介します。