2009-07-30 22 views
1

私はVisual Studio 2005を使用しています。LuaスクリプトからC++関数を呼び出すにはどうすればよいですか?

------------------------ [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)) 

答えて

5

いくつかの問題があります。私はそれらを記述して、このサンプルが動作することを意図したと思ったときに動作するはずのコードフラグメントを提供します。

最初の問題は、C++コンパイラがDLLからエクスポートされた名前がLua:luaopen_luapassing()に関係する唯一の関数の名前を変更したことです。 WindowsのストックバイナリディストリビューションはCプログラムとしてコンパイルされ、DLLモジュールのエントリポイントのCスタイル名を前提としています。

また、luaopen_x機能のプロトコルが多少間違っています。この関数は整数を返します。整数を返します。これは、Luaのスタックの一番上にあるアイテムの数がLuaによって使用される戻り値であることをLuaに通知します。 requireが前提とするプロトコルは、新しいモジュールのテーブルオブジェクトをスタックの一番上に残して、それをLuaに返す方が望ましいでしょう。これを行うには、luaopen_x関数は、通常はluaL_register()を使用してから1を返します。

名前の問題もあります。純粋なルアで書かれたモジュールは、自分の名前を認識する機会がありません。しかし、Cで書かれたモジュールは、その名前にモジュール名を含むDLLから関数をエクスポートしなければなりません。また、モジュール名をluaL_register()に指定する必要があります。これにより、グローバル環境で正しい表が作成および更新されます。最後に、クライアントのLuaスクリプトは、ロードされたモジュールをrequireに渡された名前のようなグローバルテーブルに表示します。requireからも返され、そのスクリプトのローカルにキャッシュされます。

Cコードと他のニットのカップルが数値型が本当に移植性のためlua_Numberを綴られるべきであること、そして関数に必要な引数を強制するluaL_checknumber()ではなくlua_tonumber()を使用する従来のだろうということです。個人的には、私はLuaが公に知っている名前に関連する名前を持つ公開関数をC実装に命名しますが、これは単なる趣味の問題です。

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()という名前が見つかりません。私は私が実際にコンパイルされ、上記を実行していないことを追加する必要がありますので、タイプミスまたは2があるかもしれません

 
require "luapassing" 

print("hola") 
print(luapassing.dothis(120)) 

は、私は私の答えで説明したよう、それは非常に重要です練習として;-)

2

C++としてコンパイルしていて、 'C'インターフェイスに一致させたい場合は、外部から見える関数をextern "C"と宣言し、名前のマングリングを避けます。

+0

を残しましたLuaコア自体がC++としてコンパイルされていない限り、luaopen_modulename()関数はextern "C"となることを意味します。それでも、DLLでの癖のために、複数のコンパイラがプロジェクトで使用されている場合は、問題を避けるためにextern "C"を残しておくほうがよいでしょう。 – RBerteig

3

あなたが結合LUAしてC++をたくさんやっているつもりなら、あなたはluabindを見てみたいことがあります。

関連する問題