質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
Lua

Luaは、汎用のスクリプト言語の一つで、 移植性が高く、高速な実行速度などの特徴を持ち 手続き型・オブジェクト指向言語としても利用可能で 関数型言語、データ駆動型の要素も併せ持っている言語です。

Q&A

1回答

5948閲覧

luaでの参照渡しの仕方

anatawa12

総合スコア56

Lua

Luaは、汎用のスクリプト言語の一つで、 移植性が高く、高速な実行速度などの特徴を持ち 手続き型・オブジェクト指向言語としても利用可能で 関数型言語、データ駆動型の要素も併せ持っている言語です。

0グッド

0クリップ

投稿2017/03/16 23:26

編集2022/01/12 10:55

いまcで書かれたものをluaに書き換えようと思っています
その際にdefineで定義されたマクロ関数を書き直す際に、
luaで関数内で引数を書き換えたら実引数も書き換わるということができたらなと思いました。
やり方はありますか?

やりたいこと:

c

1#define X(x) x=0

のようなものを使いたいです
そもそも実行はluajで行うので、cのソースを呼び出すことはありません

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

C/C++ 側の#defineやconstexprは そのまま Luaで使えないので以下のようにする必要があります

cpp

1#define MAXLENGTH 50 2const int MAXLENGTH = 50; 3constexpr int MAXLENGTH = 50; // C++11以降 4lua_pushinteger(L, MAXLENGTH); 5lua_setglobal(L, "MAXLENGTH");

上記のMAXLENGTHをLuaから参照する場合は以下のようにします。

lua

1print(MAXLENGTH)

逆に Luaのグローバル変数の値を C/C++で取得する場合は以下のようにします。

lua

1message = "ハローワールド"

cpp

1lua_getglobal(L, "message"); 2const char* message = lua_tostring(L, 1);

C/C++で定義した関数を Luaで使うには
int 関数名(lua_State* L);のようにする必要があります。

cpp

1int add(int x, int y) { 2 return x + y; 3} 4 5int addGlue(lua_State *L) { 6 // 引数2つをスタックから取得 7 int x = luaL_checkinteger(L, 1); 8 int y = luaL_checkinteger(L, 2); 9 10 // Luaから取得した値は残ったままになっているので空っぽにする 11 lua_settop(L, 0); 12 13 // 実際の関数を実行 14 int ret = add(x, y); 15 16 // 実行した結果を Luaのスタックに戻す 17 lua_pushinteger(L, ret); 18 19 // 引数の数を返す 20 return 1; 21} 22

Luaから add関数をよびだすには lua_registerでlua_Stateを引数に持った関数を登録必要があります。
これは luaL_openlibsを実行したあとに追加します。

これを呼び出す Lua側は

lua

1print(add(10, 9))

Luaの関数を C/C++から呼び出す方法についても書いておきます。

lua

1function init() 2 return { width = 640, height = 480 } 3end

このような関数は工夫が必要となります。

cpp

1// 呼ぶ関数 2lua_getglobal(L, "init"); 3 4// 引数なし、戻り値1個として実行 5if (lua_pcall(L, 0, 1, 0) != 0) { 6 cout << "error:" << lua_tostring(L, -1) << endl; 7 return 0; 8} 9 10// テーブルの値を二つ取得 11lua_getfield(L, 1, "width"); 12lua_getfield(L, 1, "height"); 13 14// テーブルが先頭の要素を指すので2番目と3番目を取得 15int width = lua_tointeger(L, 2); 16int height = lua_tointeger(L, 3); 17 18// Luaのスタックを空っぽにしておく 19lua_settop(L, 0);

Luaのスタックを把握するために以下のような関数を作っておくと便利です。

cpp

1// スタックの指定インデックスのアイテムの内容を表示する 2static void PrintStackItem(lua_State *L, int idx) 3{ 4 int type = lua_type(L, idx); 5 switch (type) { 6 case LUA_TSTRING: 7 // 文字列アイテムの内容表示 8 printf("index %3d : type = %s\t: \"%s\"\n", 9 idx, lua_typename(L, type), lua_tostring(L, idx)); 10 break; 11 case LUA_TNUMBER: 12 // 数値アイテムの内容表示 13 printf("index %3d : type = %s : %f\n", 14 idx, lua_typename(L, type), lua_tonumber(L, idx)); 15 break; 16 case LUA_TBOOLEAN: 17 // ブール値アイテムの内容表示 18 printf("index %3d : type = %s : \"%s\"\n", 19 idx, lua_typename(L, type), lua_toboolean(L, idx) ? "true" : "false"); 20 break; 21 default: 22 // その他ならば型だけ表示 23 printf("index %3d : type = %s \n", idx, lua_typename(L, type)); 24 break; 25 } 26[リンク内容](https://github.com/ThePhD/sol2) 27} 28 29// スタックのアイテムの内容を一覧で出力する 30void PrintStack(lua_State *L) 31{ 32 printf("----- stack -----\n"); 33 int top = lua_gettop(L); 34 // 正のインデックスで指定 35 for (int i = top; i >= 1; i--) { 36 PrintStackItem(L, i); 37 } 38 printf("-------------------\n"); 39 // 負のインデックスで指定 40 for (int i = -1; i >= -top; i--) { 41 PrintStackItem(L, i); 42 } 43 printf("-------------------\n"); 44}

もう一つですが、Sol2というC++用のライブラリを使えば
例えば以下の Luaスクリプトで定義されているテーブル、グローバル変数、テーブルをいとも簡単に使えるようになっています。

lua

1-- test.lua 2function init() 3return { 4width = 640, 5height = 480 6}; 7end 8 9function initmoji() 10return { 11returnmoji = "moji" 12}; 13end

この init関数とinitmoji関数は戻り値としてテーブルを返します。このLuaスクリプトをSol2で書くと以下のように取得できます。

cpp

1#include <iostream> 2#include <sol.hpp> 3using namespace std; 4 5int main() 6{ 7 sol::state lua; 8 lua.open_libraries(sol::lib::base, sol::lib::coroutine, sol::lib::debug, sol::lib::io, sol::lib::math, 9 sol::lib::os, sol::lib::package, sol::lib::string, sol::lib::table, sol::lib::utf8); 10 11 try { 12 lua.safe_script_file("test.lua"); 13 } 14 catch (sol::error& e) { 15 cout << e.what() << endl; 16 } 17 18 // Solを使えば簡単にテーブルから値が取り出せます。 19 sol::table ret = lua["init"](); 20 cout << "width:" << ret["width"].get<int>() << endl; 21 cout << "height:" << ret["height"].get<int>() << endl; 22 23 sol::table ret2 = lua["initmoji"](); 24 cout << ret2["returnmoji"].get<std::string>() << endl; 25}

投稿2017/12/24 23:34

編集2017/12/28 05:30
naohiro19_

総合スコア178

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問