Add Python support for std::unique_ptr inputs

Equivalent to Java/C# implementation.
This commit is contained in:
William S Fulton 2022-07-16 13:14:40 +01:00
commit c3c061cac8
8 changed files with 103 additions and 9 deletions

View file

@ -53,7 +53,7 @@ struct KlassInheritance : virtual Klass {
}
};
#if defined(SWIGJAVA) || defined (SWIGCSHARP)
#if defined(SWIGJAVA) || defined (SWIGCSHARP) || defined(SWIGPYTHON)
std::string takeKlassUniquePtr(std::unique_ptr<Klass> k) {
return std::string(k->getLabel());
}

View file

@ -1,5 +1,70 @@
from cpp11_std_unique_ptr import *
def checkCount(expected_count):
actual_count = Klass.getTotal_count()
if (actual_count != expected_count):
raise RuntimeError("Counts incorrect, expected:" + expected_count + " actual:" + actual_count)
# unique_ptr as input
kin = Klass("KlassInput")
checkCount(1)
s = takeKlassUniquePtr(kin)
checkCount(0)
if kin.thisown:
raise RuntimeError("thisown should be false")
if s != "KlassInput":
raise RuntimeError("Incorrect string: " + s)
if not is_nullptr(kin):
raise RuntimeError("is_nullptr failed")
del kin # Should not fail, even though already deleted
checkCount(0)
kin = Klass("KlassInput")
checkCount(1)
s = takeKlassUniquePtr(kin)
checkCount(0)
if kin.thisown:
raise RuntimeError("thisown should be false")
if s != "KlassInput":
raise RuntimeError("Incorrect string: " + s)
if not is_nullptr(kin):
raise RuntimeError("is_nullptr failed")
exception_thrown = False
try:
s = takeKlassUniquePtr(kin)
except RuntimeError as e:
exception_thrown = True
if not exception_thrown:
raise RuntimeError("double usage of takeKlassUniquePtr should have been an error")
del kin # Should not fail, even though already deleted
checkCount(0)
kin = Klass("KlassInput")
exception_thrown = False
try:
notowned = get_not_owned_ptr(kin)
takeKlassUniquePtr(notowned)
except RuntimeError as e:
exception_thrown = True
if not exception_thrown:
raise RuntimeError("Should have thrown 'Cannot release ownership as memory is not owned' error")
del kin
checkCount(0)
kini = KlassInheritance("KlassInheritanceInput")
checkCount(1)
s = takeKlassUniquePtr(kini)
checkCount(0)
if kini.thisown:
raise RuntimeError("thisown should be false")
if s != "KlassInheritanceInput":
raise RuntimeError("Incorrect string: " + s)
if not is_nullptr(kini):
raise RuntimeError("is_nullptr failed")
del kini # Should not fail, even though already deleted
checkCount(0)
# unique_ptr as output
k1 = makeKlassUniquePtr("first")
k2 = makeKlassUniquePtr("second")
if Klass.getTotal_count() != 2:

View file

@ -1357,12 +1357,19 @@ SWIG_Python_ConvertPtrAndOwn(PyObject *obj, void **ptr, swig_type_info *ty, int
}
}
if (sobj) {
if (((flags & SWIG_POINTER_RELEASE) == SWIG_POINTER_RELEASE) && !sobj->own) {
res = SWIG_ERROR_RELEASE_NOT_OWNED;
} else {
if (own)
*own = *own | sobj->own;
if (flags & SWIG_POINTER_DISOWN) {
sobj->own = 0;
}
if (flags & SWIG_POINTER_CLEAR) {
sobj->ptr = 0;
}
res = SWIG_OK;
}
} else {
if (implicit_conv) {
SwigPyClientData *data = ty ? (SwigPyClientData *) ty->clientdata : 0;

View file

@ -8,9 +8,22 @@
* ----------------------------------------------------------------------------- */
%define %unique_ptr(TYPE)
%typemap(in, noblock=1) std::unique_ptr< TYPE > (void *argp = 0, int res = 0) {
res = SWIG_ConvertPtr($input, &argp, $descriptor(TYPE *), SWIG_POINTER_RELEASE | %convertptr_flags);
if (!SWIG_IsOK(res)) {
if (res == SWIG_ERROR_RELEASE_NOT_OWNED) {
%releasenotowned_fail(res, "TYPE *", $symname, $argnum);
} else {
%argument_fail(res, "TYPE *", $symname, $argnum);
}
}
$1.reset((TYPE *)argp);
}
%typemap (out) std::unique_ptr< TYPE > %{
%set_output(SWIG_NewPointerObj($1.release(), $descriptor(TYPE *), SWIG_POINTER_OWN | %newpointer_flags));
%}
%template() std::unique_ptr< TYPE >;
%enddef

View file

@ -1,4 +1,4 @@
/* Errors in SWIG */
/* SWIG Errors applicable to all language modules, values are reserved from -1 to -99 */
#define SWIG_UnknownError -1
#define SWIG_IOError -2
#define SWIG_RuntimeError -3
@ -13,4 +13,3 @@
#define SWIG_MemoryError -12
#define SWIG_NullReferenceError -13

View file

@ -44,6 +44,8 @@
#define SWIG_POINTER_DISOWN 0x1
#define SWIG_CAST_NEW_MEMORY 0x2
#define SWIG_POINTER_NO_NULL 0x4
#define SWIG_POINTER_CLEAR 0x8
#define SWIG_POINTER_RELEASE (SWIG_POINTER_CLEAR | SWIG_POINTER_DISOWN)
/* Flags for new pointer objects */
#define SWIG_POINTER_OWN 0x1
@ -129,7 +131,13 @@
*/
#define SWIG_OK (0)
/* Runtime errors are < 0 */
#define SWIG_ERROR (-1)
/* Errors in range -1 to -99 are in swigerrors.swg (errors for all languages including those not using the runtime) */
/* Errors in range -100 to -199 are language specific errors defined in *errors.swg */
/* Errors < -200 are generic runtime specific errors */
#define SWIG_ERROR_RELEASE_NOT_OWNED (-200)
#define SWIG_IsOK(r) (r >= 0)
#define SWIG_ArgError(r) ((r != SWIG_ERROR) ? r : SWIG_TypeError)
@ -144,7 +152,7 @@
#define SWIG_OLDOBJ (SWIG_OK)
#define SWIG_NEWOBJ (SWIG_OK | SWIG_NEWOBJMASK)
#define SWIG_TMPOBJ (SWIG_OK | SWIG_TMPOBJMASK)
/* Check, add and del mask methods */
/* Check, add and del object mask methods */
#define SWIG_AddNewMask(r) (SWIG_IsOK(r) ? (r | SWIG_NEWOBJMASK) : r)
#define SWIG_DelNewMask(r) (SWIG_IsOK(r) ? (r & ~SWIG_NEWOBJMASK) : r)
#define SWIG_IsNewObj(r) (SWIG_IsOK(r) && (r & SWIG_NEWOBJMASK))

View file

@ -19,6 +19,7 @@
#endif
#define %varnullref_fmt(_type,_name) %nullref_fmt() %varfail_fmt(_type, _name)
#define %outnullref_fmt(_type) %nullref_fmt() %outfail_fmt(_type)
#define %releasenotownedfail_fmt(_type,_name,_argn) "in method '" `_name` "', cannot release ownership as memory is not owned for argument " `_argn`" of type '" `_type`"'"
/* setting an error */
#define %error(code,msg...) SWIG_Error(code, msg)

View file

@ -140,6 +140,7 @@
#define %argument_nullref(type, name, argn) SWIG_exception_fail(SWIG_ValueError, %argnullref_fmt(type, name, argn))
#define %variable_fail(code, type, name) SWIG_exception_fail(%default_code(code), %varfail_fmt(type, name))
#define %variable_nullref(type, name) SWIG_exception_fail(SWIG_ValueError, %varnullref_fmt(type, name))
#define %releasenotowned_fail(code, type, name, argn) SWIG_exception_fail(%default_code(code), %releasenotownedfail_fmt(type, name, argn))
#if defined(SWIG_DIRECTOR_TYPEMAPS)
#define %dirout_fail(code, type) SWIG_DirOutFail(%default_code(code), %outfail_fmt(type))