2010-11-18 5 views
1

通常は、データがLuaの標準型(数値、文字列、ブールなど)でない場合にのみ 'userdata'をプッシュします。実行可能な関数ポインタをプッシュしますか?

void nothing(const char* stuff) 
{ 
    do_magic_things_with(stuff); 
} 

返された値が振る舞う必要があります:機能を仮定すると、そのように見えます、;

しかし、どのようにあなたが実際のLuaへのポインタを機能プッシュします(ユーザデータはLuaの関数として実行可能ではないためではないユーザデータとして)このネイティブのLua関数から返された値のように:

function things() 
    return function(stuff) 
     do_magic_things_with(stuff) 
    end 
end 

これはC APIで可能ですか?はいの場合、どのように(例が分かるでしょうか)?

EDIT:明快さを追加するために、値はC APIを介してLuaに公開された関数によって返されるはずです。

答えて

1

あなたは__callメタメソッドを通して、あなたのC関数をプロキシメタテーブルでユーザデータを返すことができます。そうすることで、ユーザデータを関数のように呼び出すことができます。以下は完全なプログラムの例です。振り返ってみると、I完全にオーバー思ったあなたが求めているもの

#include <lua.h> 
#include <lualib.h> 
#include <lauxlib.h> 
#include <stdio.h> 

/* this is the C function you want to return */ 
static void 
cfunction(const char *s) 
{ 
    puts(s); 
} 

/* this is the proxy function that will be used as the __call metamethod */ 
static int 
proxy(lua_State *L) 
{ 
    luaL_checkudata(L, 1, "proxy"); 
    cfunction(luaL_checkstring(L, 2)); 
    return 0; 
} 

/* this global function returns the C function with a userdata proxy */ 
static int 
getproxy(lua_State *L) 
{ 
    lua_newuserdata(L, sizeof (int)); 
    luaL_getmetatable(L, "proxy"); 
    lua_setmetatable(L, -2); 
    return 1; 
} 

int 
main(int argc, char **argv) 
{ 
    lua_State *L; 

    L = luaL_newstate(); 

    /* create the proxy metatable */ 
    luaL_newmetatable(L, "proxy"); 
    lua_pushcfunction(L, proxy); 
    lua_setfield(L, -2, "__call"); 

    /* set the global function that returns the proxy */ 
    lua_pushcfunction(L, getproxy); 
    lua_setglobal(L, "getproxy"); 

    /* see if it works */ 
    luaL_dostring(L, "p = getproxy() p('Hello, world!')"); 

    lua_close(L); 

    return 0; 
} 

。あなたが本当に必要とするのは、Luaスタックからパラメータを引き出し、それらをターゲットのC関数に渡すlua_CFunction型の関数を作成することだけです。上記のコードは文字通りあなたの質問に答えますが、実際に達成する必要があるのはおそらく過剰です。

+1

WAAAYが設計されています。 –

+0

@caspinだから最後の編集とDougの答えに対する私のコメント。これを歴史的な文脈の中に置くために、彼は最初にDougの答えに投票し、問題を考えるのをやめました。 –

9

使用lua_pushcfunction

としては、ここで現在受け入れ答えの形態を以下の実施例であるPiL

に含まれています。

#include <lua.h> 
#include <lualib.h> 
#include <lauxlib.h> 
#include <stdio.h> 

/* this is the C function you want to return */ 
static void 
cfunction(const char *s) 
{ 
    puts(s); 
} 

/* this is the proxy function that acts like cfunction */ 
static int 
proxy(lua_State *L) 
{ 
    cfunction(luaL_checkstring(L, 1)); 
    return 0; 
} 

/* this global function returns "cfunction" to Lua. */ 
static int 
getproxy(lua_State *L) 
{ 
    lua_pushcfunction(L, &proxy); 
    return 1; 
} 

int 
main(int argc, char **argv) 
{ 
    lua_State *L; 

    L = luaL_newstate(); 

    /* set the global function that returns the proxy */ 
    lua_pushcfunction(L, getproxy); 
    lua_setglobal(L, "getproxy"); 

    /* see if it works */ 
    luaL_dostring(L, "p = getproxy() p('Hello, world!')"); 

    lua_close(L); 

    return 0; 
} 
+0

Downvote 'lua_pushcfunction'は' lua_CFunction'をプッシュします。これは明らかに 'lua_CFunction'タイプのみである可能性があります。 –

+4

これは当てはまりますが、lua_CFunction型の関数を作成して、Luaスタックからパラメータを引き出し、それらをターゲットのC関数に渡すことができます。これはバインディングの作成と呼ばれています! –

+0

私は今参照してください。さて、この回答は受け入れられたと考えてください。残念ながら私は正式に1つしか受け入れることができません。 –

関連する問題