Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 9 additions & 5 deletions docs/dev/Lua API.rst
Original file line number Diff line number Diff line change
Expand Up @@ -129,10 +129,12 @@ All typed objects have the following built-in features:

Returns *size, address*

* ``ref:new()``
* ``ref:new([assign_table])``

Allocates a new instance of the same type, and copies data
from the current object.
from the current object,
then optionally calls ``ref:assign`` with a Lua table of
:ref:`data to be assigned <lua-api-table-assignment>` to the new instance.

* ``ref:delete()``

Expand Down Expand Up @@ -355,9 +357,11 @@ Types excluding the global object also support:

Returns the size of an object of the type.

* ``type:new()``
* ``type:new([assign_table])``

Creates a new instance of an object of the type.
Creates a new instance of an object of the type,
then optionally calls ``ref:assign`` with a Lua table of
:ref:`data to be assigned <lua-api-table-assignment>` to the new instance.

* ``type:is_instance(object)``

Expand Down Expand Up @@ -427,7 +431,7 @@ The ``df`` table itself contains the following functions and values:
For types and refs identical to ``obj:sizeof()``.
For lightuserdata returns *nil, address*

* ``df.new(obj)``, ``df.delete(obj)``, ``df.assign(obj, obj2)``
* ``df.new(obj[,assign_data])``, ``df.delete(obj)``, ``df.assign(obj, obj2)``

Equivalent to using the matching methods of obj.

Expand Down
16 changes: 14 additions & 2 deletions library/LuaWrapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -695,15 +695,17 @@ static int meta_new(lua_State *state)
int argc = lua_gettop(state);

if (argc != 1 && argc != 2)
luaL_error(state, "Usage: object:new() or df.new(object) or df.new(ptype,count)");
luaL_error(state, "Usage: object:new() or object:new(assign_table) or df.new(object) or df.new(object, assign_table) or df.new(ptype,count)");

const type_identity *id = get_object_identity(state, 1, "df.new()", true);

void *ptr = nullptr;
std::string err_context;

auto has_assign_table = (argc == 2 && lua_istable(state, 2));

// Support arrays of primitive types
if (argc == 2)
if (argc == 2 && !has_assign_table)
{
int cnt = luaL_checkint(state, 2);
if (cnt <= 0)
Expand Down Expand Up @@ -745,6 +747,16 @@ static int meta_new(lua_State *state)
else
push_object_internal(state, id, ptr);

if (has_assign_table) {
// stack: 1 = the source object or type, 2 = the assign table, (... there could be junk here but currently isn't...), -1 = the new object that will be returned.
lua_dup(state); // duplicate the object we just new'ed
lua_getfield(state, -1, "assign"); // get its assign method
lua_swap(state); // shuffle the two
lua_pushvalue(state, 2); // copy arg 2, the table of assign data
lua_call(state, 2, 0); // call assign(), two args, we don't care what it returns.
// TODO this leaks the allocated object if assign fails.
// TODO maybe we should copy the table and insert a field "new = false".
}
return 1;
}

Expand Down
Loading