Add Lua support for std::unique_ptr and std::auto_ptr

Equivalent to Python/Ruby implementations.
This commit is contained in:
William S Fulton 2022-08-11 21:37:16 +01:00
commit 41fddf61ec
7 changed files with 186 additions and 11 deletions

View file

@ -7,6 +7,10 @@ the issue number to the end of the URL: https://github.com/swig/swig/issues/
Version 4.1.0 (in progress) Version 4.1.0 (in progress)
=========================== ===========================
2022-08-11: wsfulton
[Lua] Add support for std::unique_ptr in std_unique_ptr.i.
Add support for std::auto_ptr in std_auto_ptr.i.
2022-08-05: wsfulton 2022-08-05: wsfulton
[D] Fix occasional undefined behaviour with inheritance hierarchies, particularly [D] Fix occasional undefined behaviour with inheritance hierarchies, particularly
when using virtual inheritance as the pointers weren't correctly upcast from derived when using virtual inheritance as the pointers weren't correctly upcast from derived

View file

@ -1,6 +1,6 @@
%module cpp11_std_unique_ptr %module cpp11_std_unique_ptr
#if defined(SWIGCSHARP) || defined(SWIGJAVA) || defined(SWIGPYTHON) || defined(SWIGRUBY) || defined(SWIGPERL) || defined(SWIGTCL) || defined(SWIGOCTAVE) || defined(SWIGJAVASCRIPT) || defined(SWIGD) || defined(SWIGPHP) #if !(defined(SWIGGO) || defined(SWIGOCAML) || defined(SWIGMZSCHEME) || defined(SWIGR) || defined(SWIGSCILAB))
%include "std_string.i" %include "std_string.i"
%include "std_unique_ptr.i" %include "std_unique_ptr.i"

View file

@ -12,7 +12,7 @@
#endif #endif
%} %}
#if defined(SWIGCSHARP) || defined(SWIGJAVA) || defined(SWIGPYTHON) || defined(SWIGRUBY) || defined(SWIGPERL) || defined(SWIGTCL) || defined(SWIGOCTAVE) || defined(SWIGJAVASCRIPT) || defined(SWIGD) || (SWIGPHP) #if !(defined(SWIGGO) || defined(SWIGOCAML) || defined(SWIGMZSCHEME) || defined(SWIGR) || defined(SWIGSCILAB))
%include "std_string.i" %include "std_string.i"
//#include <iostream> //#include <iostream>

View file

@ -0,0 +1,93 @@
require("import") -- the import fn
import("li_std_auto_ptr") -- import code
-- catch "undefined" global variables
local env = _ENV -- Lua 5.2
if not env then env = getfenv () end -- Lua 5.1
setmetatable(env, {__index=function (t,i) error("undefined global variable `"..i.."'",2) end})
function checkCount(expected_count)
-- call gc to make unused objects are collected
collectgarbage()
actual_count = li_std_auto_ptr.Klass.getTotal_count()
if not (actual_count == expected_count) then
error("Counts incorrect, expected:"..expected_count.." actual:"..actual_count)
end
end
--Test raw pointer handling involving virtual inheritance
kini = li_std_auto_ptr.KlassInheritance("KlassInheritanceInput")
checkCount(1)
s = li_std_auto_ptr.useKlassRawPtr(kini)
if not (s == "KlassInheritanceInput") then
error("Incorrect string: "..s)
end
kini = nil
checkCount(0)
-- auto_ptr as input
kin = li_std_auto_ptr.Klass("KlassInput")
checkCount(1)
s = li_std_auto_ptr.takeKlassAutoPtr(kin)
checkCount(0)
if not (s == "KlassInput") then
error("Incorrect string: "..s)
end
if not (li_std_auto_ptr.is_nullptr(kin)) then
error("is_nullptr failed")
end
kin = nil -- Should not fail, even though already deleted
checkCount(0)
kin = li_std_auto_ptr.Klass("KlassInput")
checkCount(1)
s = li_std_auto_ptr.takeKlassAutoPtr(kin)
checkCount(0)
if not (s == "KlassInput") then
error("Incorrect string: "..s)
end
if not (li_std_auto_ptr.is_nullptr(kin)) then
error("is_nullptr failed")
end
s, msg = pcall(function() li_std_auto_ptr.takeKlassAutoPtr(kin) end)
assert(s == false and msg == "Cannot release ownership as memory is not owned for argument 1 of type 'Klass *' in takeKlassAutoPtr")
kin = nil -- Should not fail, even though already deleted
checkCount(0)
kin = li_std_auto_ptr.Klass("KlassInput")
notowned = li_std_auto_ptr.get_not_owned_ptr(kin)
s, msg = pcall(function() li_std_auto_ptr.takeKlassAutoPtr(notowned) end)
assert(s == false and msg == "Cannot release ownership as memory is not owned for argument 1 of type 'Klass *' in takeKlassAutoPtr")
checkCount(1)
kin = nil
checkCount(0)
kini = li_std_auto_ptr.KlassInheritance("KlassInheritanceInput")
checkCount(1)
s = li_std_auto_ptr.takeKlassAutoPtr(kini)
checkCount(0)
if not (s == "KlassInheritanceInput") then
error("Incorrect string: "..s)
end
if not (li_std_auto_ptr.is_nullptr(kini)) then
error("is_nullptr failed")
end
kini = nil -- Should not fail, even though already deleted
checkCount(0)
-- auto_ptr as output
k1 = li_std_auto_ptr.makeKlassAutoPtr("first")
k2 = li_std_auto_ptr.makeKlassAutoPtr("second")
checkCount(2)
k1 = nil
checkCount(1)
if not (k2:getLabel() == "second") then
error("wrong object label")
end
k2 = nil
checkCount(0)

View file

@ -1757,6 +1757,7 @@ SWIGRUNTIME void SWIG_Lua_NewPointerObj(lua_State *L,void *ptr,swig_type_info *t
(if possible) */ (if possible) */
SWIGRUNTIME int SWIG_Lua_ConvertPtr(lua_State *L,int index,void **ptr,swig_type_info *type,int flags) SWIGRUNTIME int SWIG_Lua_ConvertPtr(lua_State *L,int index,void **ptr,swig_type_info *type,int flags)
{ {
int ret = SWIG_ERROR;
swig_lua_userdata *usr; swig_lua_userdata *usr;
swig_cast_info *cast; swig_cast_info *cast;
/* special case: lua nil => NULL pointer */ /* special case: lua nil => NULL pointer */
@ -1773,25 +1774,36 @@ SWIGRUNTIME int SWIG_Lua_ConvertPtr(lua_State *L,int index,void **ptr,swig_type
usr=(swig_lua_userdata*)lua_touserdata(L,index); /* get data */ usr=(swig_lua_userdata*)lua_touserdata(L,index); /* get data */
if (usr) if (usr)
{ {
if (((flags & SWIG_POINTER_RELEASE) == SWIG_POINTER_RELEASE) && !usr->own)
{
return SWIG_ERROR_RELEASE_NOT_OWNED;
}
if (flags & SWIG_POINTER_DISOWN) /* must disown the object */ if (flags & SWIG_POINTER_DISOWN) /* must disown the object */
{ {
usr->own=0; usr->own = 0;
} }
if (!type) /* special cast void*, no casting fn */ if (!type) /* special cast void*, no casting fn */
{ {
*ptr=usr->ptr; *ptr=usr->ptr;
return SWIG_OK; /* ok */ ret = SWIG_OK;
} }
cast=SWIG_TypeCheckStruct(usr->type,type); /* performs normal type checking */ else
if (cast)
{ {
int newmemory = 0; cast=SWIG_TypeCheckStruct(usr->type,type); /* performs normal type checking */
*ptr=SWIG_TypeCast(cast,usr->ptr,&newmemory); if (cast)
assert(!newmemory); /* newmemory handling not yet implemented */ {
return SWIG_OK; /* ok */ int newmemory = 0;
*ptr=SWIG_TypeCast(cast,usr->ptr,&newmemory);
assert(!newmemory); /* newmemory handling not yet implemented */
ret = SWIG_OK;
}
}
if ((ret == SWIG_OK) && (flags & SWIG_POINTER_CLEAR))
{
usr->ptr = 0;
} }
} }
return SWIG_ERROR; /* error */ return ret;
} }
SWIGRUNTIME void* SWIG_Lua_MustGetPtr(lua_State *L,int index,swig_type_info *type,int flags, SWIGRUNTIME void* SWIG_Lua_MustGetPtr(lua_State *L,int index,swig_type_info *type,int flags,

33
Lib/lua/std_auto_ptr.i Normal file
View file

@ -0,0 +1,33 @@
/* -----------------------------------------------------------------------------
* std_auto_ptr.i
*
* SWIG library file for handling std::auto_ptr.
* Memory ownership is passed from the std::auto_ptr C++ layer to the proxy
* class when returning a std::auto_ptr from a function.
* Memory ownership is passed from the proxy class to the std::auto_ptr in the
* C++ layer when passed as a parameter to a wrapped function.
* ----------------------------------------------------------------------------- */
%define %auto_ptr(TYPE)
%typemap(in, checkfn="lua_isuserdata", noblock=1) std::auto_ptr< TYPE > (void *argp = 0, int res = 0) {
res = SWIG_ConvertPtr(L, $input, &argp, $descriptor(TYPE *), SWIG_POINTER_RELEASE);
if (!SWIG_IsOK(res)) {
if (res == SWIG_ERROR_RELEASE_NOT_OWNED) {
lua_pushfstring(L, "Cannot release ownership as memory is not owned for argument $argnum of type 'TYPE *' in $symname"); SWIG_fail;
} else {
SWIG_fail_ptr("$symname", $argnum, $descriptor(TYPE *));
}
}
$1.reset((TYPE *)argp);
}
%typemap (out) std::auto_ptr< TYPE > %{
SWIG_NewPointerObj(L, $1.release(), $descriptor(TYPE *), SWIG_POINTER_OWN); SWIG_arg++;
%}
%template() std::auto_ptr< TYPE >;
%enddef
namespace std {
template <class T> class auto_ptr {};
}

33
Lib/lua/std_unique_ptr.i Normal file
View file

@ -0,0 +1,33 @@
/* -----------------------------------------------------------------------------
* std_unique_ptr.i
*
* SWIG library file for handling std::unique_ptr.
* Memory ownership is passed from the std::unique_ptr C++ layer to the proxy
* class when returning a std::unique_ptr from a function.
* Memory ownership is passed from the proxy class to the std::unique_ptr in the
* C++ layer when passed as a parameter to a wrapped function.
* ----------------------------------------------------------------------------- */
%define %unique_ptr(TYPE)
%typemap(in, checkfn="lua_isuserdata", noblock=1) std::unique_ptr< TYPE > (void *argp = 0, int res = 0) {
res = SWIG_ConvertPtr(L, $input, &argp, $descriptor(TYPE *), SWIG_POINTER_RELEASE);
if (!SWIG_IsOK(res)) {
if (res == SWIG_ERROR_RELEASE_NOT_OWNED) {
lua_pushfstring(L, "Cannot release ownership as memory is not owned for argument $argnum of type 'TYPE *' in $symname"); SWIG_fail;
} else {
SWIG_fail_ptr("$symname", $argnum, $descriptor(TYPE *));
}
}
$1.reset((TYPE *)argp);
}
%typemap (out) std::unique_ptr< TYPE > %{
SWIG_NewPointerObj(L, $1.release(), $descriptor(TYPE *), SWIG_POINTER_OWN); SWIG_arg++;
%}
%template() std::unique_ptr< TYPE >;
%enddef
namespace std {
template <class T> class unique_ptr {};
}