Hi,
Thank you so much for taking the time to write a detailed reply. I didn't realize that the C registry is accessible from Lua and so I wrote a patch for loadlib.c with the C code given later.
Now that I see from your code that this can be done from Lua itself, I'll do that. The other way you suggested using upvalues definitely looks clever, I'll see if that works for my case :)
It does make me nervous that everyone is a bit quiet about unloading libraries. Guess I'll just risk it and hope for the best :D !
C Code:
static int removePathFromInternalCLIBSList(lua_State *L, void *plib) {
int indexToRemove = 0;
lua_rawgetp(L, LUA_REGISTRYINDEX, &CLIBS);
lua_pushnil(L); /* first key */
while (lua_next(L, -2) != 0) {
/* uses 'key' (at index -2) and 'value' (at index -1) */
/*sprintf(buffer + strlen(buffer), "%s - %s\n",
lua_typename(L, lua_type(L, -2)),
lua_typename(L, lua_type(L, -1)));*/
if (lua_type(L, -2) == LUA_TNUMBER) {
//sprintf(buffer + strlen(buffer), "NUMBER: %d -> userdata\n\n", (int)lua_tonumber(L, -2)/*, (int)lua_tonumber(L, -1)*/);
void *plibVal = lua_touserdata(L, -1);
if (plib == plibVal) {
indexToRemove = (int)lua_tonumber(L, -2);
lua_pop(L, 2);
break;
}
}
/* removes 'value'; keeps 'key' for next iteration */
lua_pop(L, 1);
}
// Now the entry at indexToRemove must be removed from the array portion of CLIBS
if (indexToRemove > 0) {
lua_getglobal(L, "table");
lua_getfield(L, -1, "remove");
lua_replace(L, -2); // remove _G.table
lua_rawgetp(L, LUA_REGISTRYINDEX, &CLIBS);
lua_pushinteger(L, indexToRemove);
lua_call(L, 2, 0);
}
else {
return -1;
}
return 0;
}
/*
** registry.CLIBS[path] = plib -- for queries
** registry.CLIBS[#CLIBS + 1] = plib -- also keep a list of all libraries
*/
static int removeCLIBPathFromRegistry(lua_State *L) {
const char *path = luaL_checkstring(L, 1);
void *plib = checkclib(L, path);
// Try clearing the index of the C library from the array part of CLIBS
int errorCode = removePathFromInternalCLIBSList(L, plib);
if (errorCode < 0) {
return luaL_error(L, "package.removeCLIBPathFromRegistry: Unable to locate index of C library in registry.CLIBS: %s", path);
}
lua_rawgetp(L, LUA_REGISTRYINDEX, &CLIBS);
lua_pushnil(L);
lua_setfield(L, -2, path); /* CLIBS[path] = nil */
lua_pop(L, 1); /* pop CLIBS table */
return 0;
}
Thanks again!
Abhijit