Fix directorin SWIGTYPE typemaps to make a copy as these are used for pass by value.
Closes #434
This commit is contained in:
parent
b062d998e9
commit
98a31ff633
15 changed files with 180 additions and 14 deletions
|
|
@ -5,6 +5,13 @@ See the RELEASENOTES file for a summary of changes in each release.
|
||||||
Version 3.0.9 (in progress)
|
Version 3.0.9 (in progress)
|
||||||
===========================
|
===========================
|
||||||
|
|
||||||
|
2016-05-14: wsfulton
|
||||||
|
Fix #434 - Passing classes by value as parameters in director methods did not create
|
||||||
|
a copy of the argument leading to invalid memory accesses if the object was used
|
||||||
|
after the upcall into the target language. Passing arguments by value shouldn't give
|
||||||
|
rise to these sorts of memory problems and so the objects are now copied and ownership
|
||||||
|
of their lifetime is controlled by the target language.
|
||||||
|
|
||||||
2016-05-07: wsfulton
|
2016-05-07: wsfulton
|
||||||
Fix #611. Fix assertion handling defaultargs when using %extend for a template
|
Fix #611. Fix assertion handling defaultargs when using %extend for a template
|
||||||
class and the extended methods contain default arguments.
|
class and the extended methods contain default arguments.
|
||||||
|
|
|
||||||
|
|
@ -174,7 +174,6 @@ CPP_TEST_CASES += \
|
||||||
director_abstract \
|
director_abstract \
|
||||||
director_alternating \
|
director_alternating \
|
||||||
director_basic \
|
director_basic \
|
||||||
director_property \
|
|
||||||
director_binary_string \
|
director_binary_string \
|
||||||
director_classes \
|
director_classes \
|
||||||
director_classic \
|
director_classic \
|
||||||
|
|
@ -189,12 +188,14 @@ CPP_TEST_CASES += \
|
||||||
director_ignore \
|
director_ignore \
|
||||||
director_keywords \
|
director_keywords \
|
||||||
director_namespace_clash \
|
director_namespace_clash \
|
||||||
|
director_nested \
|
||||||
director_nspace \
|
director_nspace \
|
||||||
director_nspace_director_name_collision \
|
director_nspace_director_name_collision \
|
||||||
director_nested \
|
|
||||||
director_overload \
|
director_overload \
|
||||||
director_overload2 \
|
director_overload2 \
|
||||||
|
director_pass_by_value \
|
||||||
director_primitives \
|
director_primitives \
|
||||||
|
director_property \
|
||||||
director_protected \
|
director_protected \
|
||||||
director_protected_overloaded \
|
director_protected_overloaded \
|
||||||
director_redefined \
|
director_redefined \
|
||||||
|
|
|
||||||
43
Examples/test-suite/csharp/director_pass_by_value_runme.cs
Normal file
43
Examples/test-suite/csharp/director_pass_by_value_runme.cs
Normal file
|
|
@ -0,0 +1,43 @@
|
||||||
|
using System;
|
||||||
|
using director_pass_by_valueNamespace;
|
||||||
|
|
||||||
|
public class runme
|
||||||
|
{
|
||||||
|
private static void WaitForGC()
|
||||||
|
{
|
||||||
|
System.GC.Collect();
|
||||||
|
System.GC.WaitForPendingFinalizers();
|
||||||
|
System.Threading.Thread.Sleep(10);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void Main()
|
||||||
|
{
|
||||||
|
runme r = new runme();
|
||||||
|
r.run();
|
||||||
|
}
|
||||||
|
|
||||||
|
void run()
|
||||||
|
{
|
||||||
|
Caller caller = new Caller();
|
||||||
|
caller.call_virtualMethod(new director_pass_by_value_Derived());
|
||||||
|
{
|
||||||
|
int countdown = 5;
|
||||||
|
while (true) {
|
||||||
|
WaitForGC();
|
||||||
|
if (--countdown == 0)
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
// bug was the passByVal 'global' object was destroyed after the call to virtualMethod had finished.
|
||||||
|
int ret = runme.passByVal.getVal();
|
||||||
|
if (ret != 0x12345678)
|
||||||
|
throw new Exception("Bad return value, got " + ret.ToString("x"));
|
||||||
|
}
|
||||||
|
public static PassedByValue passByVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
class director_pass_by_value_Derived : DirectorPassByValueAbstractBase {
|
||||||
|
public override void virtualMethod(PassedByValue pbv) {
|
||||||
|
runme.passByVal = pbv;
|
||||||
|
}
|
||||||
|
}
|
||||||
30
Examples/test-suite/director_pass_by_value.i
Normal file
30
Examples/test-suite/director_pass_by_value.i
Normal file
|
|
@ -0,0 +1,30 @@
|
||||||
|
%module(directors="1") director_pass_by_value
|
||||||
|
%director DirectorPassByValueAbstractBase;
|
||||||
|
|
||||||
|
%inline %{
|
||||||
|
class PassedByValue {
|
||||||
|
int val;
|
||||||
|
public:
|
||||||
|
PassedByValue() { val = 0x12345678; }
|
||||||
|
int getVal() { return val; }
|
||||||
|
};
|
||||||
|
|
||||||
|
int doSomething(int x) {
|
||||||
|
int yy[256];
|
||||||
|
yy[0] =0x9876;
|
||||||
|
return yy[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
class DirectorPassByValueAbstractBase {
|
||||||
|
public:
|
||||||
|
virtual void virtualMethod(PassedByValue pbv) = 0;
|
||||||
|
virtual ~DirectorPassByValueAbstractBase () {}
|
||||||
|
};
|
||||||
|
|
||||||
|
class Caller {
|
||||||
|
public:
|
||||||
|
void call_virtualMethod(DirectorPassByValueAbstractBase &f) {
|
||||||
|
f.virtualMethod(PassedByValue());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
%}
|
||||||
48
Examples/test-suite/java/director_pass_by_value_runme.java
Normal file
48
Examples/test-suite/java/director_pass_by_value_runme.java
Normal file
|
|
@ -0,0 +1,48 @@
|
||||||
|
|
||||||
|
import director_pass_by_value.*;
|
||||||
|
|
||||||
|
public class director_pass_by_value_runme {
|
||||||
|
|
||||||
|
static {
|
||||||
|
try {
|
||||||
|
System.loadLibrary("director_pass_by_value");
|
||||||
|
} catch (UnsatisfiedLinkError e) {
|
||||||
|
System.err.println("Native code library failed to load. See the chapter on Dynamic Linking Problems in the SWIG Java documentation for help.\n" + e);
|
||||||
|
System.exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void WaitForGC() {
|
||||||
|
System.gc();
|
||||||
|
System.runFinalization();
|
||||||
|
try {
|
||||||
|
java.lang.Thread.sleep(10);
|
||||||
|
} catch (java.lang.InterruptedException e) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String argv[]) {
|
||||||
|
Caller caller = new Caller();
|
||||||
|
caller.call_virtualMethod(new director_pass_by_value_Derived());
|
||||||
|
{
|
||||||
|
int countdown = 5;
|
||||||
|
while (true) {
|
||||||
|
WaitForGC();
|
||||||
|
if (--countdown == 0)
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
// bug was the passByVal 'global' object was destroyed after the call to virtualMethod had finished.
|
||||||
|
int ret = director_pass_by_value_runme.passByVal.getVal();
|
||||||
|
if (ret != 0x12345678)
|
||||||
|
throw new RuntimeException("Bad return value, got " + Integer.toHexString(ret));
|
||||||
|
}
|
||||||
|
|
||||||
|
static PassedByValue passByVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
class director_pass_by_value_Derived extends DirectorPassByValueAbstractBase {
|
||||||
|
public void virtualMethod(PassedByValue pbv) {
|
||||||
|
director_pass_by_value_runme.passByVal = pbv;
|
||||||
|
}
|
||||||
|
}
|
||||||
24
Examples/test-suite/php/director_pass_by_value_runme.php
Normal file
24
Examples/test-suite/php/director_pass_by_value_runme.php
Normal file
|
|
@ -0,0 +1,24 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
require "tests.php";
|
||||||
|
require "director_pass_by_value.php";
|
||||||
|
|
||||||
|
$passByVal = null;
|
||||||
|
|
||||||
|
class director_pass_by_value_Derived extends DirectorPassByValueAbstractBase {
|
||||||
|
function virtualMethod($b) {
|
||||||
|
global $passByVal;
|
||||||
|
$passByVal = $b;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# bug was the passByVal global object was destroyed after the call to virtualMethod had finished.
|
||||||
|
$caller = new Caller();
|
||||||
|
$caller->call_virtualMethod(new director_pass_by_value_Derived());
|
||||||
|
$ret = $passByVal->getVal();
|
||||||
|
if ($ret != 0x12345678) {
|
||||||
|
check::fail("Bad return value, got " . dechex($ret));
|
||||||
|
}
|
||||||
|
|
||||||
|
check::done();
|
||||||
|
?>
|
||||||
13
Examples/test-suite/python/director_pass_by_value_runme.py
Normal file
13
Examples/test-suite/python/director_pass_by_value_runme.py
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
import director_pass_by_value
|
||||||
|
|
||||||
|
passByVal = None
|
||||||
|
class director_pass_by_value_Derived(director_pass_by_value.DirectorPassByValueAbstractBase):
|
||||||
|
def virtualMethod(self, b):
|
||||||
|
global passByVal
|
||||||
|
passByVal = b
|
||||||
|
|
||||||
|
# bug was the passByVal global object was destroyed after the call to virtualMethod had finished.
|
||||||
|
director_pass_by_value.Caller().call_virtualMethod(director_pass_by_value_Derived())
|
||||||
|
ret = passByVal.getVal();
|
||||||
|
if ret != 0x12345678:
|
||||||
|
raise RuntimeError("Bad return value, got " + hex(ret))
|
||||||
|
|
@ -409,8 +409,8 @@ SWIGINTERN const char * SWIG_UnpackData(const char *c, void *ptr, size_t sz) {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
%typemap(directorin) SWIGTYPE
|
%typemap(directorin) SWIGTYPE
|
||||||
%{ $input = (void *)&$1; %}
|
%{ $input = (void *)new $1_ltype((const $1_ltype &)$1); %}
|
||||||
%typemap(csdirectorin) SWIGTYPE "new $&csclassname($iminput, false)"
|
%typemap(csdirectorin) SWIGTYPE "new $&csclassname($iminput, true)"
|
||||||
%typemap(csdirectorout) SWIGTYPE "$&csclassname.getCPtr($cscall).Handle"
|
%typemap(csdirectorout) SWIGTYPE "$&csclassname.getCPtr($cscall).Handle"
|
||||||
|
|
||||||
/* Generic pointers and references */
|
/* Generic pointers and references */
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,7 @@
|
||||||
$*csclassname ret = (cPtr == global::System.IntPtr.Zero) ? null : new $*csclassname(cPtr, $owner);$excode
|
$*csclassname ret = (cPtr == global::System.IntPtr.Zero) ? null : new $*csclassname(cPtr, $owner);$excode
|
||||||
return ($*csinterfacename)ret;
|
return ($*csinterfacename)ret;
|
||||||
}
|
}
|
||||||
%typemap(csdirectorin) CTYPE "($&csinterfacename)new $&csclassname($iminput, false)"
|
%typemap(csdirectorin) CTYPE "($&csinterfacename)new $&csclassname($iminput, true)"
|
||||||
%typemap(csdirectorin) CTYPE & "($csinterfacename)new $csclassname($iminput, false)"
|
%typemap(csdirectorin) CTYPE & "($csinterfacename)new $csclassname($iminput, false)"
|
||||||
%typemap(csdirectorin) CTYPE *, CTYPE [] "($iminput == global::System.IntPtr.Zero) ? null : ($csinterfacename)new $csclassname($iminput, false)"
|
%typemap(csdirectorin) CTYPE *, CTYPE [] "($iminput == global::System.IntPtr.Zero) ? null : ($csinterfacename)new $csclassname($iminput, false)"
|
||||||
%typemap(csdirectorin) CTYPE *const& "($iminput == global::System.IntPtr.Zero) ? null : ($*csinterfacename)new $*csclassname($iminput, false)"
|
%typemap(csdirectorin) CTYPE *const& "($iminput == global::System.IntPtr.Zero) ? null : ($*csinterfacename)new $*csclassname($iminput, false)"
|
||||||
|
|
|
||||||
|
|
@ -57,7 +57,7 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
%typemap(directorin) SWIGTYPE
|
%typemap(directorin) SWIGTYPE
|
||||||
"$input = (void *)&$1;"
|
"$input = (void *)new $1_ltype((const $1_ltype &)$1);"
|
||||||
%typemap(directorout) SWIGTYPE
|
%typemap(directorout) SWIGTYPE
|
||||||
%{ if (!$input) {
|
%{ if (!$input) {
|
||||||
SWIG_DSetPendingException(SWIG_DIllegalArgumentException, "Unexpected null return for type $1_type");
|
SWIG_DSetPendingException(SWIG_DIllegalArgumentException, "Unexpected null return for type $1_type");
|
||||||
|
|
@ -65,7 +65,7 @@
|
||||||
}
|
}
|
||||||
$result = *($&1_ltype)$input; %}
|
$result = *($&1_ltype)$input; %}
|
||||||
|
|
||||||
%typemap(ddirectorin) SWIGTYPE "new $&dclassname($winput, false)"
|
%typemap(ddirectorin) SWIGTYPE "new $&dclassname($winput, true)"
|
||||||
%typemap(ddirectorout) SWIGTYPE "$&dclassname.swigGetCPtr($dcall)"
|
%typemap(ddirectorout) SWIGTYPE "$&dclassname.swigGetCPtr($dcall)"
|
||||||
|
|
||||||
%typemap(din) SWIGTYPE "$&dclassname.swigGetCPtr($dinput)"
|
%typemap(din) SWIGTYPE "$&dclassname.swigGetCPtr($dinput)"
|
||||||
|
|
|
||||||
|
|
@ -584,7 +584,7 @@
|
||||||
%typemap(goout) SWIGTYPE ""
|
%typemap(goout) SWIGTYPE ""
|
||||||
|
|
||||||
%typemap(directorin) SWIGTYPE
|
%typemap(directorin) SWIGTYPE
|
||||||
%{ $input = ($&1_ltype)&$1; %}
|
%{ $input = new $1_ltype((const $1_ltype &)$1); %}
|
||||||
|
|
||||||
%typemap(godirectorin) SWIGTYPE ""
|
%typemap(godirectorin) SWIGTYPE ""
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -647,8 +647,8 @@ SWIGINTERN const char * SWIG_UnpackData(const char *c, void *ptr, size_t sz) {
|
||||||
|
|
||||||
%typemap(directorin,descriptor="L$packagepath/$&javaclassname;") SWIGTYPE
|
%typemap(directorin,descriptor="L$packagepath/$&javaclassname;") SWIGTYPE
|
||||||
%{ $input = 0;
|
%{ $input = 0;
|
||||||
*(($&1_ltype*)&$input) = &$1; %}
|
*(($&1_ltype*)&$input) = new $1_ltype((const $1_ltype &)$1); %}
|
||||||
%typemap(javadirectorin) SWIGTYPE "new $&javaclassname($jniinput, false)"
|
%typemap(javadirectorin) SWIGTYPE "new $&javaclassname($jniinput, true)"
|
||||||
%typemap(javadirectorout) SWIGTYPE "$&javaclassname.getCPtr($javacall)"
|
%typemap(javadirectorout) SWIGTYPE "$&javaclassname.getCPtr($javacall)"
|
||||||
|
|
||||||
/* Generic pointers and references */
|
/* Generic pointers and references */
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,7 @@
|
||||||
return (cPtr == 0) ? null : ($javainterfacename)new $javaclassname(cPtr, $owner);
|
return (cPtr == 0) ? null : ($javainterfacename)new $javaclassname(cPtr, $owner);
|
||||||
}
|
}
|
||||||
|
|
||||||
%typemap(javadirectorin) CTYPE "($&javainterfacename)new $&javaclassname($jniinput, false)"
|
%typemap(javadirectorin) CTYPE "($&javainterfacename)new $&javaclassname($jniinput, true)"
|
||||||
%typemap(javadirectorin) CTYPE & "($javainterfacename)new $javaclassname($jniinput, false)"
|
%typemap(javadirectorin) CTYPE & "($javainterfacename)new $javaclassname($jniinput, false)"
|
||||||
%typemap(javadirectorin) CTYPE *, CTYPE [] "($jniinput == 0) ? null : ($javainterfacename)new $javaclassname($jniinput, false)"
|
%typemap(javadirectorin) CTYPE *, CTYPE [] "($jniinput == 0) ? null : ($javainterfacename)new $javaclassname($jniinput, false)"
|
||||||
%typemap(javadirectorin) CTYPE *const& "($jniinput == 0) ? null : ($*javainterfacename)new $*javaclassname($jniinput, false)"
|
%typemap(javadirectorin) CTYPE *const& "($jniinput == 0) ? null : ($*javainterfacename)new $*javaclassname($jniinput, false)"
|
||||||
|
|
@ -40,7 +40,7 @@
|
||||||
%typemap(javadirectorout) CTYPE *const& "$javacall.$*interfacename_GetInterfaceCPtr()"
|
%typemap(javadirectorout) CTYPE *const& "$javacall.$*interfacename_GetInterfaceCPtr()"
|
||||||
%typemap(directorin,descriptor="L$packagepath/$&javainterfacename;") CTYPE
|
%typemap(directorin,descriptor="L$packagepath/$&javainterfacename;") CTYPE
|
||||||
%{ $input = 0;
|
%{ $input = 0;
|
||||||
*(($&1_ltype*)&$input) = &$1; %}
|
*(($&1_ltype*)&$input) = new $1_ltype((const $1_ltype &)$1); %}
|
||||||
%typemap(directorin,descriptor="L$packagepath/$javainterfacename;") CTYPE *, CTYPE []
|
%typemap(directorin,descriptor="L$packagepath/$javainterfacename;") CTYPE *, CTYPE []
|
||||||
%{ *(($&1_ltype)&$input) = ($1_ltype) $1; %}
|
%{ *(($&1_ltype)&$input) = ($1_ltype) $1; %}
|
||||||
%typemap(directorin,descriptor="L$packagepath/$javainterfacename;") CTYPE &
|
%typemap(directorin,descriptor="L$packagepath/$javainterfacename;") CTYPE &
|
||||||
|
|
|
||||||
|
|
@ -429,7 +429,7 @@
|
||||||
|
|
||||||
%typemap(directorin) SWIGTYPE
|
%typemap(directorin) SWIGTYPE
|
||||||
{
|
{
|
||||||
SWIG_SetPointerZval($input, SWIG_as_voidptr(&$1), $&1_descriptor, 2);
|
SWIG_SetPointerZval($input, SWIG_as_voidptr(new $1_ltype((const $1_ltype &)$1)), $&1_descriptor, 1|2);
|
||||||
}
|
}
|
||||||
|
|
||||||
%typemap(out) void "";
|
%typemap(out) void "";
|
||||||
|
|
|
||||||
|
|
@ -415,7 +415,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
%typemap(directorin,noblock=1) SWIGTYPE {
|
%typemap(directorin,noblock=1) SWIGTYPE {
|
||||||
$input = SWIG_NewPointerObj(%as_voidptr(&$1), $&descriptor, %newpointer_flags);
|
$input = SWIG_NewPointerObj(%as_voidptr(new $1_ltype((const $1_ltype &)$1)), $&descriptor, SWIG_POINTER_OWN | %newpointer_flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
%typemap(directorin,noblock=1) SWIGTYPE & {
|
%typemap(directorin,noblock=1) SWIGTYPE & {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue