LuaスクリプトからC ++関数を呼び出すにはどうすればよいですか?
-
06-07-2019 - |
質問
Visual Studio 2005を使用しています。
------------------------ [luapassing.cpp] ------------------ -
#include "lua.h"
static int myCfunc (Lua_State *L){
double trouble = lua_tonumber(L,1);
lua_pushnumber(L,16.0 -trouble);
return 1;
}
int luaopen_luapassing (Lua_State *L){
static const lua_reg Map [] = {{"dothis",myCfunc},{NULL,NULL}};
luaL_register(L,"cstuff",Map);
return;
}
------------------------- [csample.lua] ----------------- --------
package.cpath = "./CLua2.dll"
require "luapassing"
print("hola")
print(seth.doThis(120))
解決
いくつかの問題があります。それらについて説明し、このサンプルが機能することを意図していると思われるように機能するはずのコードフラグメントを提供します。
最初の問題は、C ++コンパイラが、Luaにとって重要なDLLからエクスポートされた唯一の関数の名前をマングルしたことです: luaopen_luapassing()
。 Windows用のストックバイナリディストリビューションはCプログラムとしてコンパイルされ、DLLモジュールのエントリポイントにCスタイル名を想定しています。
また、 luaopen_x
関数のプロトコルが少し間違っています。この関数は、Luaのスタックの最上部にあるLuaが使用する戻り値の数をLuaに伝える整数を返します。 require
が想定しているプロトコルは、新しいモジュールのテーブルオブジェクトをスタックの一番上に残して、Luaに返すことを好みます。これを行うには、 luaopen_x
関数は通常どおり luaL_register()
を使用し、1を返します。
ネーミングの問題もあります。純粋なLuaで書かれたモジュールには、その名前をあまり知らない機会があります。ただし、Cで記述されたモジュールは、名前にモジュール名を含むDLLから関数をエクスポートする必要があります。また、グローバル環境で正しいテーブルが作成および更新されるように、モジュール名を luaL_register()
に提供する必要があります。最後に、クライアントLuaスクリプトは、 require
に渡される名前のような名前のグローバルテーブルにロードされたモジュールを表示します。そのスクリプトのローカル。
Cコードの他のいくつかの点は、移植性のために数値型は本当に lua_Number
と綴られるべきであり、 luaL_checknumber()
を使用するのが慣習的であるということです。 lua_tonumber()
ではなく、関数に必要な引数を強制します。個人的には、パブリック関数のC実装に、その名前に関連する名前を付けます。この名前はLuaによって公開されますが、それは好みの問題です。
このバージョンのCサイドでは、これらの問題を修正する必要があります。
#include "lua.h"
static int my_dothis (Lua_State *L){
lua_Number trouble = luaL_checknumber(L,1);
lua_pushnumber(L,16.0 -trouble);
return 1;
}
extern "C" int luaopen_luapassing (Lua_State *L){
static const lua_reg Map [] = {
{"dothis", my_dothis},
{NULL,NULL}
};
luaL_register(L,"luapassing",Map);
return 1;
}
サンプルスクリプトは、ロードされたモジュールを適切な名前で参照し、そのモジュールで定義された関数を適切な名前で参照する必要があります。 Luaは大文字と小文字を区別するため、モジュールが dothis()
という名前の関数を作成する場合、スクリプトは同じ名前を使用する必要があり、 doThis()
という名前の関数を見つけることができません。例。
require "luapassing" print("hola") print(luapassing.dothis(120))
実際にコンパイルして上記を実行していないことを追加する必要があります。そのため、演習として1つまたは2つのタイプミスが残っている可能性があります;-)
他のヒント
多くのC ++からluaバインディングを行う場合は、 luabind 。
C ++としてコンパイルしていて、「C」インターフェースに一致させたい場合は、名前のマングリングを避けるために、外部から見える関数を extern" C"
として宣言する必要があります。