lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


2017-11-02 12:54 GMT+02:00 Viacheslav Usov <via.usov@gmail.com>:
> On Thu, Nov 2, 2017 at 8:41 AM, Marc Balmer <marc@msys.ch> wrote:
>
>> Is it possible to create a luaL_Buffer over several calls to Lua
>> functions?  E.g. like in the following pseudo code:
>
> [...]
>
>>  Or must all buffer operations be finished when I return from C code?

> I am unsure why such a dangerous facility is present, but I think that its
> dangers should be stressed by stronger language. The problem is that the
> crash happens only when large strings are stuffed into the buffer, which is
> a perfect ingredient for "it works when I test it, but it crashes randomly
> in production, and no one knows why".

It is there for greater efficiency.

> I think it can also be made less dangerous by using a reference to the
> userdatum rather than the top of the stack, but frankly, I think this is
> something that should only be used by Lua itself and its public use
> deprecated.

Oh, that is overstating the case. The public (or at least that section
of it that can write code in the Lua C API) is not so delicate.

What I envisaged in my earlier reply is in fact quite easy, almost
trivial. See attachment. (Lua 5.3).
/* buffer.c © Dirk Laurie 2017  MIT license like Lua 
   Compile with: cc -shared buffer.c -o buffer.so
   If you get a message containing the hint "recompile with -fPIC"., obey it.
   I.e.

      cc -shared buffer.c -fPIC -o buffer.so 

   Exercise for the reader: add a Lua front-end that allows object-oriented
   calls. i.e. buf:append(item) instead of buffer.append(buf,item) etc. 
   The metatable is already there. */

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

static int buffer_new (lua_State *L) {
  lua_newuserdata(L,sizeof(luaL_Buffer));
  luaL_buffinit(L, (luaL_Buffer*) lua_topointer(L,-1));
  luaL_setmetatable(L,"Buffer");
  return 1;
}

static int buffer_flush (lua_State *L) {
  luaL_Buffer* buf = (luaL_Buffer*) luaL_checkudata(L,1,"Buffer");
  luaL_pushresult(buf);
  return 1;   
}

static int buffer_append (lua_State *L) {
  luaL_Buffer* buf = (luaL_Buffer*) luaL_checkudata(L,1,"Buffer");
  luaL_addvalue(buf);
  return 0; 
}

static const luaL_Reg buffer_funcs[] = {
  {"new", buffer_new},
  {"flush", buffer_flush},
  {"append", buffer_append},
  {NULL, NULL}
};

LUAMOD_API int luaopen_buffer (lua_State *L) {
  luaL_newmetatable (L, "Buffer");
  luaL_newlib(L, buffer_funcs);
  return 1;
}