2015-09-24 2 views
4

Как я интегрирую Lua в мою программу на C, я использовал указатель static для структуры C для хранения объекта, который мне нужно повторно использовать в методах, которые я связываю с Lua государство.Сохранение структуры C в реестре Lua

Однако это не сработает, когда я разделил Lua lib из основной программы, поэтому мне кажется, что мне нужно использовать реестр для хранения моей структуры.

Как мне сохранить мой указатель структуры C в реестре Lua?

Это то, что я сейчас делаю:

static augeas *aug = NULL; 


static int lua_aug_get(lua_State *L) { 
    // Use aug to do something here 
    /* return the number of results */ 
    return 1; 
} 

struct lua_State *luaopen_augeas(augeas *a) { 
    lua_State *L = luaL_newstate(); 
    aug = a; // this clearly does not work 
    luaL_openlibs(L); 
    // The methods below will need to access the augeas * struct 
    // so I need to push it to the registry (I guess) 
    static const luaL_Reg augfuncs[] = { 
     { "get", lua_aug_get }, 
     { "label", lua_aug_label }, 
     { "set", lua_aug_set }, 
     { NULL, NULL } 
    }; 

    luaL_newlib(L, augfuncs); 
    lua_setglobal(L, "aug"); 

    return L; 
} 

Edit: от ответа я получил на IRC, мне кажется, я должен использовать в metatable, так что я в настоящее время изучает это.

ответ

3

Если реестр не безопасно-достаточно места для хранения указателя, вы можете поместить его в качестве конкретных повышать стоимость функций:

static int lua_aug_get(lua_State *L) { 
    augeas *aug = lua_touserdata(L, lua_upvalueindex(1)); 
    // Do stuff with aug 
    return 1; 
} 

static const luaL_Reg augfuncs[] = { 
    { "get", lua_aug_get }, 
    { "label", lua_aug_label }, 
    { "set", lua_aug_set }, 
    { NULL, NULL } 
}; 
lua_createtable(L, 0, 0); 
for (size_t i = 0; augfuncs[i].name; i++) { 
    lua_pushlightuserdata(L, a); 
    lua_pushcclosure(L, augfuncs[i].func, 1); 
    lua_setfield(L, -2, augfuncs[i].name); 
} 

Но это хорошо, чтобы сохранить его в реестре. Он не доступен для сценариев, за исключением библиотеки debug, обычно не отображаемой в песочницах. И если другие библиотеки создают эгоистичный беспорядок там, вы все равно в беде.

1

мне удалось получить его на работу с помощью индекса Lua реестра и толкая указатель, как света UserData:

static const char *Key = "augeas_registry_key"; // The registry key 

static augeas *checkaug(lua_State *L) { 
    lua_pushlightuserdata(L, (void *)&Key);  // set the registry key 
    lua_gettable(L, LUA_REGISTRYINDEX);   // retrieve value 
    augeas *aug = (augeas *)lua_touserdata(L, -1); // cast value 
    return aug; 
} 

static int lua_aug_get(lua_State *L) { 
    augeas *aug = checkaug(L); 
    // Do stuff with aug 
    return 1; 
} 

struct lua_State *luaopen_augeas(augeas *a) { 
    lua_State *L = luaL_newstate(); 
    luaL_openlibs(L); 

    lua_pushlightuserdata(L, (void *)&Key); // set registry key 
    lua_pushlightuserdata(L, (void *)a); // push pointer 
    lua_settable(L, LUA_REGISTRYINDEX);  // push to in registry 

    static const luaL_Reg augfuncs[] = { 
     { "get", lua_aug_get }, 
     { "label", lua_aug_label }, 
     { "set", lua_aug_set }, 
     { NULL, NULL } 
    }; 

    luaL_newlib(L, augfuncs); 
    lua_setglobal(L, "aug"); 

    return L; 
} 

Это не очень элегантно, хотя, учитывая, что использует общий реестр, который может быть доступный для других библиотек, загруженных во время сеанса, поэтому я по-прежнему открыт для лучшего варианта.

Смежные вопросы