diff options
author | William S Fulton <wsf@fultondesigns.co.uk> | 2022-08-11 21:37:16 +0100 |
---|---|---|
committer | William S Fulton <wsf@fultondesigns.co.uk> | 2022-08-11 21:38:21 +0100 |
commit | 41fddf61ec6aa253b6a531ef33dd78fef5925e4a (patch) | |
tree | 16c4d66b9d53ea277271b771803237dbf4b4b50f | |
parent | 63632f80fb815aef2577aaa495fdbe369c880ab2 (diff) | |
download | swig-41fddf61ec6aa253b6a531ef33dd78fef5925e4a.tar.gz |
Add Lua support for std::unique_ptr and std::auto_ptr
Equivalent to Python/Ruby implementations.
-rw-r--r-- | CHANGES.current | 4 | ||||
-rw-r--r-- | Examples/test-suite/cpp11_std_unique_ptr.i | 2 | ||||
-rw-r--r-- | Examples/test-suite/li_std_auto_ptr.i | 2 | ||||
-rw-r--r-- | Examples/test-suite/lua/li_std_auto_ptr_runme.lua | 93 | ||||
-rw-r--r-- | Lib/lua/luarun.swg | 30 | ||||
-rw-r--r-- | Lib/lua/std_auto_ptr.i | 33 | ||||
-rw-r--r-- | Lib/lua/std_unique_ptr.i | 33 |
7 files changed, 186 insertions, 11 deletions
diff --git a/CHANGES.current b/CHANGES.current index bb16fef2d..8554c5a2d 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -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) =========================== +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 [D] Fix occasional undefined behaviour with inheritance hierarchies, particularly when using virtual inheritance as the pointers weren't correctly upcast from derived diff --git a/Examples/test-suite/cpp11_std_unique_ptr.i b/Examples/test-suite/cpp11_std_unique_ptr.i index 285eedf5a..2defdd445 100644 --- a/Examples/test-suite/cpp11_std_unique_ptr.i +++ b/Examples/test-suite/cpp11_std_unique_ptr.i @@ -1,6 +1,6 @@ %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_unique_ptr.i" diff --git a/Examples/test-suite/li_std_auto_ptr.i b/Examples/test-suite/li_std_auto_ptr.i index 49615e0b5..ee007c777 100644 --- a/Examples/test-suite/li_std_auto_ptr.i +++ b/Examples/test-suite/li_std_auto_ptr.i @@ -12,7 +12,7 @@ #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 <iostream> diff --git a/Examples/test-suite/lua/li_std_auto_ptr_runme.lua b/Examples/test-suite/lua/li_std_auto_ptr_runme.lua new file mode 100644 index 000000000..f677a6e4e --- /dev/null +++ b/Examples/test-suite/lua/li_std_auto_ptr_runme.lua @@ -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) diff --git a/Lib/lua/luarun.swg b/Lib/lua/luarun.swg index 572da4703..909a5229c 100644 --- a/Lib/lua/luarun.swg +++ b/Lib/lua/luarun.swg @@ -1757,6 +1757,7 @@ SWIGRUNTIME void SWIG_Lua_NewPointerObj(lua_State *L,void *ptr,swig_type_info *t (if possible) */ 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_cast_info *cast; /* 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 */ 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 */ { - usr->own=0; + usr->own = 0; } if (!type) /* special cast void*, no casting fn */ { *ptr=usr->ptr; - return SWIG_OK; /* ok */ + ret = SWIG_OK; } - cast=SWIG_TypeCheckStruct(usr->type,type); /* performs normal type checking */ - if (cast) + else { - int newmemory = 0; - *ptr=SWIG_TypeCast(cast,usr->ptr,&newmemory); - assert(!newmemory); /* newmemory handling not yet implemented */ - return SWIG_OK; /* ok */ + cast=SWIG_TypeCheckStruct(usr->type,type); /* performs normal type checking */ + if (cast) + { + 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, diff --git a/Lib/lua/std_auto_ptr.i b/Lib/lua/std_auto_ptr.i new file mode 100644 index 000000000..b0978963b --- /dev/null +++ b/Lib/lua/std_auto_ptr.i @@ -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 {}; +} diff --git a/Lib/lua/std_unique_ptr.i b/Lib/lua/std_unique_ptr.i new file mode 100644 index 000000000..de84b2497 --- /dev/null +++ b/Lib/lua/std_unique_ptr.i @@ -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 {}; +} |