2011-03-27 34 views
3

CreateEntity是我在項目中綁定到Lua的C函數。它將實體類名稱字符串作爲第一個參數,並將任何數量的附加參數傳遞給所選實體的構造函數。Lua C API:處理和存儲其他參數

例如,如果CreateEntity是一個正常的Lua的功能,我可以做這種方式:

function CreateEntity(class, ...) 
    -- (choose a constructor function based on class) 
    args = {...} 
    -- (store args somewhere for whatever reason) 
    TheConstructor(...) 
end 

但我怎麼能做到這一點與C Lua的功能?

+0

添加lua標記,因爲實際上有一些追隨者。 – BMitch 2011-03-27 13:34:43

+6

爲#lua追隨者而歡呼! ;) – sbk 2011-03-27 14:37:18

+0

你在C或C++嗎? – Puppy 2011-03-27 20:42:00

回答

1
args = {...} 
-- (store args somewhere for whatever reason) 

The arguments of the call are on the Lua stack,你可以與他們爲你做,請:把它們放在自己的結構(std::vector<boost::any>或類似的東西)或者個人參數存儲在the Lua registry或創建的參數和存儲一個Lua表在註冊表中。什麼適合你更好?

TheConstructor(...) 

我相當確信這個部分是不可能的在C++中的方式是在Lua中。 C++需要在編譯時傳遞給函數的參數數量。

這是在C++中嘗試和執行這些操作的主要不便之處。如果你告訴我們爲什麼你想讓你的CreateEntity函數在C++端而不是在Lua上,也許會有更好的解決方案。

+0

我認爲你錯過了這一點。他不想編寫這樣工作的C++函數,他想用Lua C API完成上述任務。 – Puppy 2011-03-27 20:41:32

+0

也許我錯過了這點......但我仍然無法看到如何用一個運行時參數列表調用一個C++方法(我認爲'TheConstructor'是一個),而不訴諸asm hack或使構造函數知道Lua 。我很想在這個上被證明是錯誤的 – sbk 2011-03-27 21:53:58

4

C函數lua_gettop將返回傳遞給C函數的參數數量。您必須從堆棧中讀取所有內容並將它們存儲在C數據結構中,或將它們放入Lua註冊表中(請參閱RegistryluaL_ref),並存儲對它們的引用以備將來使用。下面的示例程序使用註冊表方法。

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

/* this function prints the name and extra variables as a demonstration */ 
static void 
TheConstructor(lua_State *L, const char *name, int *registry, int n) 
{ 
    int i; 

    puts(name); 

    for (i = 0; i < n; ++i) { 
     lua_rawgeti(L, LUA_REGISTRYINDEX, registry[i]); 
     puts(lua_tostring(L, -1)); 
    } 

    free(registry); 
} 

static int 
CreateEntity(lua_State *L) 
{ 
    const char *NAME = luaL_checkstring(L, 1); 
    int *registry; 
    int i, n; 

    /* remove the name parameter from the stack */ 
    lua_remove(L, 1); 

    /* check how many arguments are left */ 
    n = lua_gettop(L); 

    /* create an array of registry entries */ 
    registry = calloc(n, sizeof (int)); 
    for (i = n; i > 0; --i) 
     registry[i-1] = luaL_ref(L, LUA_REGISTRYINDEX); 

    TheContructor(L, NAME, registry, n); 

    return 0; 
} 

int 
main(int argc, char **argv[]) 
{ 
    const char TEST_CHUNK[] = 
     "CreateEntity('foo', 1, 2, 3, 4, 5, 6, 7, 8, 9, 10)"; 
    lua_State *L; 

    L = luaL_newstate(); 
    lua_register(L, "CreateEntity", CreateEntity); 
    luaL_dostring(L, TEST_CHUNK); 
    lua_close(L); 

    return EXIT_SUCCESS; 
}