2015-03-28 2 views
2

Несмотря на жесткий поиск, я не смог найти допустимый пример API Lua C для вызова функции Lua, возвращающей пользовательские данные из функции C. Например, у меня есть функция регистрации «GetMyVector», а затем я вызываю это из lua для получения информации из C, то, что я получил, является таблицей, но то, что я хочу, - это что-то вроде доступа к переменной доступа из struct, как в C, для пример:Lua возвращает пользовательские данные из функции C

local x = GetMyVector() 
print(x[1]) -- i 
print(x[2]) -- j 
print(x[3]) -- k 
-- how to access it via like this: 
print(x.i) 
print(x.j) 
print(x.k) 

моя C функция толкая вектор в 3 одномерный массив по lua_pushnumber:

static int GetMyVector(lua_State *L) 
{ 
    vec3_t vec; 
    vec[0] = 1; 
    vec[1] = 2; 
    vec[3] = 3; 
    lua_newtable(L); 
    lua_pushnumber(L, vec[0]); 
    lua_rawseti(L, -2, 1); 
    lua_pushnumber(L, vec[1]); 
    lua_rawseti(L, -2, 2); 
    lua_pushnumber(L, vec[2]); 
    lua_rawseti(L, -2, 3); 
    return 1; 
} 
+1

И? Это работает? –

+0

_ «Если у вас есть учебник и информация об этом, пожалуйста, вставьте lnk ниже, я по достоинству оценю его». _ Вопросы, предлагающие нам рекомендовать или находить книгу, инструмент, библиотеку программного обеспечения, учебник или другой ресурс вне сайта, тема для переполнения стека, поскольку они склонны привлекать упрямые ответы и спам. Вместо этого опишите проблему и то, что было сделано до сих пор, чтобы ее решить. –

+0

Да, мне удалось это исправить, но, честно говоря, я не знаю, что делать, потому что я понятия не имею, как это назвать, не могу найти никакой информации об этом, чтобы немного поработать и решить эту проблему. – user2887378

ответ

0

Это немного расширена, но благодаря @geov я нашел то, что искал, это своего рода похожи на свойства стиля, как в C# я думаю, здесь вы идете раствор:

#define MYCLASSNAME "vec" 

typedef struct { 
    int i, j, k; 
} MyVec_t; 

typedef int(*Xet_func) (lua_State *L, void *v); 

/* member info for get and set handlers */ 
typedef const struct{ 
    const char *name; /* member name */ 
    Xet_func func;  /* get or set function for type of member */ 
    size_t offset;  /* offset of member within MyVec_t */ 
} Xet_reg_pre; 

typedef Xet_reg_pre * Xet_reg; 

// properties 
static int Get_Int(lua_State *L, void *v) { 
    lua_pushnumber(L, *(int*)v); 
    return 1; 
} 

static int Set_Int(lua_State *L, void *v) { 
    *(int*)v = luaL_checkinteger(L, 3); 
    return 0; 
} 

static int Get_Number(lua_State *L, void *v) { 
    lua_pushnumber(L, *(lua_Number*)v); 
    return 1; 
} 

static int Set_Number(lua_State *L, void *v) { 
    *(lua_Number*)v = luaL_checknumber(L, 3); 
    return 0; 
} 

static int Get_String(lua_State *L, void *v) { 
    lua_pushstring(L, (char*)v); 
    return 1; 
} 

static void Property_Add(lua_State *L, Xet_reg l) 
{ 
    for (; l->name; l++) { 
     lua_pushstring(L, l->name); 
     lua_pushlightuserdata(L, (void*)l); 
     lua_settable(L, -3); 
    } 
} 

static int Property_Call(lua_State *L) 
{ 
    Xet_reg m = (Xet_reg)lua_touserdata(L, -1); 
    lua_pop(L, 1);        
    luaL_checktype(L, 1, LUA_TUSERDATA); 
    return m->func(L, (void *)((char *)lua_touserdata(L, 1) + m->offset)); 
} 

static int index_handler(lua_State *L) 
{ 
    /* stack has userdata, index */ 
    lua_pushvalue(L, 2);      /* dup index */ 
    lua_rawget(L, lua_upvalueindex(1));  /* lookup member by name */ 
    if (!lua_islightuserdata(L, -1)) { 
     lua_pop(L, 1);       /* drop value */ 
     lua_pushvalue(L, 2);     /* dup index */ 
     lua_gettable(L, lua_upvalueindex(2)); /* else try methods */ 
     if (lua_isnil(L, -1))     /* invalid member */ 
      luaL_error(L, "cannot get member '%s'", lua_tostring(L, 2)); 
     return 1; 
    } 
    return Property_Call(L);      /* call get function */ 
} 

static int newindex_handler(lua_State *L) 
{ 
    /* stack has userdata, index, value */ 
    lua_pushvalue(L, 2);      /* dup index */ 
    lua_rawget(L, lua_upvalueindex(1));  /* lookup member by name */ 
    if (!lua_islightuserdata(L, -1))   /* invalid member */ 
     luaL_error(L, "cannot set member '%s'", lua_tostring(L, 2)); 
    return Property_Call(L);      /* call set function */ 
} 

static MyVec_t *CheckMyVec(lua_State *L, int index) // get data 
{ 
    MyVec_t *p; 
    luaL_checktype(L, index, LUA_TUSERDATA); 
    p = (MyVec_t *)luaL_checkudata(L, index, MYCLASSNAME); 
    return p; 
} 

static MyVec_t *PushMyVec(lua_State *L) // push data 
{ 
    MyVec_t *p = (MyVec_t *)lua_newuserdata(L, sizeof(MyVec_t)); 
    luaL_getmetatable(L, MYCLASSNAME); 
    lua_setmetatable(L, -2); 
    return p; 
} 

static int MyVec_Create(lua_State *L) // C function which will push data 
{ 
    MyVec_t *p; 
    p = PushMyVec(L); 
    p->i = luaL_checkinteger(L, 1); 
    p->j = luaL_checkinteger(L, 2);; 
    p->k = luaL_checkinteger(L, 3);; 
    return 1; 
} 

static int MyVec_destroy(lua_State *L) 
{ 
    MyVec_t *p = (MyVec_t *)lua_touserdata(L, 1); 
    return 0; 
} 

static int MyVec_Position(lua_State *L) 
{ 
    MyVec_t *p = CheckMyVec(L, 1); 
    double x = p->i; 
    double y = p->j; 
    double z = p->k; 
    if (lua_gettop(L) > 1) { 
     p->i = luaL_checknumber(L, 2); 
     p->j = luaL_checknumber(L, 3); 
     p->k = luaL_checknumber(L, 4); 
    } 
    lua_pushnumber(L, x); 
    lua_pushnumber(L, y); 
    lua_pushnumber(L, z); 
    return 2; 
} 


static const luaL_Reg myvec_meta_methods[] = { 
    { "__gc", MyVec_destroy }, 
    { 0, 0 } 
}; 

static const luaL_Reg myvec_methods[] = { 
    { "create", MyVec_Create }, 
    { "position", MyVec_Position }, 
    { 0, 0 } 
}; 

static const Xet_reg_pre MyVec_get[] = { 
    { "i", Get_Int, offsetof(MyVec_t, i) }, 
    { "j", Get_Int, offsetof(MyVec_t, j) }, 
    { "k", Get_Int, offsetof(MyVec_t, k) }, 
    { 0, 0 } 
}; 

static const Xet_reg_pre MyVec_set[] = { 
    { "i", Set_Int, offsetof(MyVec_t, i) }, 
    { "j", Set_Int, offsetof(MyVec_t, j) }, 
    { "k", Set_Int, offsetof(MyVec_t, k) }, 
    { 0, 0 } 
}; 


int MyVec_Register(lua_State *L) 
{ 
    int metatable, methods; 

    /* create methods table, & add it to the table of globals */ 
    luaL_openlib(L, MYCLASSNAME, myvec_methods, 0); 
    methods = lua_gettop(L); 

    /* create metatable for MyVec_t, & add it to the registry */ 
    luaL_newmetatable(L, MYCLASSNAME); 
    luaL_openlib(L, 0, myvec_meta_methods, 0); /* fill metatable */ 
    metatable = lua_gettop(L); 

    lua_pushliteral(L, "__metatable"); 
    lua_pushvalue(L, methods);    /* dup methods table*/ 
    lua_rawset(L, metatable);    /* hide metatable: 
              metatable.__metatable = methods */ 
    lua_pushliteral(L, "__index"); 
    lua_pushvalue(L, metatable);   /* upvalue index 1 */ 
    Property_Add(L, MyVec_get);    /* fill metatable with getters */ 
    lua_pushvalue(L, methods);    /* upvalue index 2 */ 
    lua_pushcclosure(L, index_handler, 2); 
    lua_rawset(L, metatable);    /* metatable.__index = index_handler */ 

    lua_pushliteral(L, "__newindex"); 
    lua_newtable(L);      /* table for members you can set */ 
    Property_Add(L, MyVec_set);    /* fill with setters */ 
    lua_pushcclosure(L, newindex_handler, 1); 
    lua_rawset(L, metatable);    /* metatable.__newindex = newindex_handler */ 

    lua_pop(L, 1);       /* drop metatable */ 
    return 1;        /* return methods on the stack */ 
} 
2

Вы, вероятно, хотите lua_settable. Он позволяет устанавливать любые ключи для таблицы. Если ключ является буквальным, вы можете получить данные по x["i"] или по x.i. Код должен быть чем-то вроде

static int GetMyVector(lua_State *L) 
{ 
    vec3_t vec; 
    vec[0] = 1; 
    vec[1] = 2; 
    vec[3] = 3; 
    lua_newtable(L); 

    lua_pushliteral(L, "i"); 
    lua_pushnumber(L, vec[0]); 
    lua_settable(L, -2); 

    lua_pushliteral(L, "j"); 
    lua_pushnumber(L, vec[1]); 
    lua_settable(L, -2); 

    lua_pushliteral(L, "k"); 
    lua_pushnumber(L, vec[2]); 
    lua_settable(L, -2); 
    return 1; 
} 
Смежные вопросы