c - 在 C 中重新分配/调整 Lua 5.1 用户数据的大小

标签 c lua

如何在运行时调整 C 语言中的 Lua 5.1 用户数据对象的大小?

我想从 Lua 5.1 控制台更改 Roberto Ierusalimschy 的《Programming in Lua》一书,第 2 版,第 260 页中描述的 NumArray 结构的大小。

我的 NumArray 用户数据可以存储无符号字符或 lua_Numbers。我尝试调用 lmem.c 中定义的未修改的 luaM_realloc_ 函数,但最终对 C 的 realloc 的任何调用 (通过 l_alloc)函数仅返回 NULL,因此我收到内存不足错误消息。

有人可以帮我吗?

--- lapi.c -------------------------------------------------------------------------------------------------

LUA_API void *agn_resizeud (lua_State *L, void *block, size_t osize, size_t nsize) {
  Udata *u = (Udata *)luaM_realloc_(L, block, osize + sizeof(Udata), nsize + sizeof(Udata));
  u->uv.len = nsize;
  if (u == NULL)
    luaL_error(L, "Error in " LUA_QS ": failed to allocate memory.", "API/agn_resizeud");
  return u;
}

--- numarray.c ---------------------------------------------------------------------------------------------

#define checkarray(L, n) (NumArray *)luaL_checkudata(L, n, "numarray")

[...]

/* Auxiliary C function to finally call luaM_realloc_ via the Lua C API */

void *reallocud (lua_State *L, void *block, size_t o, size_t n, size_t sizeofelem, size_t sizeofnumarray) {
  if (n + 1 > MAX_SIZET/sizeofelem)
    luaL_error(L, "Error in " LUA_QS ": memory allocation error: block too big.", "(reallocud)", n);
  else
    return agn_resizeud(L, block, sizeofnumarray + o*sizeofelem, sizeofnumarray + n*sizeofelem);
}

/* function to resize a NumArray */

static int numarray_resize (lua_State *L) {
  size_t i;
  global_State *g = G(L);
  NumArray *a = checkarray(L, 1);
  int n = luaL_checkinteger(L, 2);
  if (n < 1)
    luaL_error(L, "Error in " LUA_QS ": new size %d is non-positive.", "numarray.resize", n);
  if (n == a->size) {   /* do nothing and do not complain */
    lua_pushinteger(L, a->size);
    return 1;
  }
  if (n > a->size) {  /* extend */
    a = reallocud(L, a, a->size, n, a->isnumber ? sizeof(lua_Number) : sizeof(char), sizeof(NumArray));
    if (a->isnumber) {
      for (i=a->size; i < n; i++) a->data.n[i] = 0;
    } else {
      for (i=a->size; i < n; i++) a->data.c[i] = 0;
    }
  } else {  /* reduce */
    if (a->isnumber) {
      for (i=a->size - 1; i > n - 1; i--) a->data.n[i] = 0;
    } else {
      for (i=a->size - 1; i > n - 1; i--) a->data.c[i] = 0;
    }
    a = reallocud(L, a, a->size, n, a->isnumber ? sizeof(lua_Number) : sizeof(char), sizeof(NumArray));
  }
  a->size = n;
  lua_pushnumber(L, a->size);
  return 1;
}

[...]

typedef struct NumArray {
  size_t size;           /* number of slots */
  char isnumber;
  union data {
    lua_Number n[1];  /* pointer to the various lua_Number values */
    unsigned char c[1];
  } data;
} NumArray;

最佳答案

没有必要搞乱 Lua 的内部结构。

但是你需要改变用户数据的创建方式:不要将结构体和数据分配在同一个内存块中,而是单独分配它们,使用lua_newuserdata来分配结构体和malloc 分配数据。

然后,要调整数据部分的大小,只需更新结构中的大小并重新分配数据部分即可。

关于c - 在 C 中重新分配/调整 Lua 5.1 用户数据的大小,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29806478/

相关文章:

c - 目前有什么好的 UNIX 编译器/链接器选项的跨平台引用吗?

c - 如何通过 fork 和 exec 执行程序

c++ - ffi.C 缺少所有符号的所有声明

lua - Love2D NewImageFont 不会渲染

Lua 错误 - 需要删除的错误参数 #1

lua - 检查目录是否存在于lua中?

带有包含空格的键的 lua 表构造函数

c - 有没有办法重置或清除 ttyusb0 read short of power cycling the computer

c - 文件描述符和进程关系

c - 套接字编程 - 为什么我们不将 sin_family 转换为网络顺序?