うたカモ技術ブログ

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.cliblua.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言語の連携が可能なスクリプト言語です。

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

参考文献

ガジェット記事も読む

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

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

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

2026年版 ドローンの選び方 基礎知識とおすすめモデル5選

2026年版 ドローンの選び方 基礎知識とおすすめモデル5選

ドローンを初めて購入する人向けに、基礎知識について整理し、DJI・HOVERAir・Potensicの代表モデルを紹介します。

初心者向けノートパソコンおすすめ10選 失敗しにくい選び方を整理

初心者向けノートパソコンおすすめ10選 失敗しにくい選び方を整理

ノートパソコンを初めて選ぶ人向けに、比較しやすい10機種を紹介します。メモリ、ストレージ、画面サイズ、重さ、Office有無、保証の見方を整理します。

OCuLinkとは何か? 小型PCやミニPCの購入前に知っておきたいポイントを整理

OCuLinkとは何か? 小型PCやミニPCの購入前に知っておきたいポイントを整理

OCuLinkとは何かを、小型PCやミニPCの購入を検討している人向けに整理します。USB4やThunderboltとの違い、eGPU用途で気にしたいポイント、製品ページでの確認点をまとめています。

3Dプリンターの選び方! 造形方式や素材、確認ポイントを整理して紹介

3Dプリンターの選び方! 造形方式や素材、確認ポイントを整理して紹介

3Dプリンターの選び方を紹介します。FDMと光造形の違い、PLAやPETG、ABSなどの素材、造形サイズ、家庭で使うときの注意点、代表的なメーカーと製品を整理しています。

超格安な日本発のマイコンボード UIAPduinoの紹介

超格安な日本発のマイコンボード UIAPduinoの紹介

290円という価格が目を引く日本発のマイコンボードについて、主な仕様、安さの背景、向 く用途、定番ボードとの違いをまとめて紹介します。