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)
|
||||
===========================
|
||||
|
||||
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
|
||||
Fix #611. Fix assertion handling defaultargs when using %extend for a template
|
||||
class and the extended methods contain default arguments.
|
||||
|
|
|
|||
|
|
@ -174,7 +174,6 @@ CPP_TEST_CASES += \
|
|||
director_abstract \
|
||||
director_alternating \
|
||||
director_basic \
|
||||
director_property \
|
||||
director_binary_string \
|
||||
director_classes \
|
||||
director_classic \
|
||||
|
|
@ -189,12 +188,14 @@ CPP_TEST_CASES += \
|
|||
director_ignore \
|
||||
director_keywords \
|
||||
director_namespace_clash \
|
||||
director_nested \
|
||||
director_nspace \
|
||||
director_nspace_director_name_collision \
|
||||
director_nested \
|
||||
director_overload \
|
||||
director_overload2 \
|
||||
director_pass_by_value \
|
||||
director_primitives \
|
||||
director_property \
|
||||
director_protected \
|
||||
director_protected_overloaded \
|
||||
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
|
||||
|
||||
%typemap(directorin) SWIGTYPE
|
||||
%{ $input = (void *)&$1; %}
|
||||
%typemap(csdirectorin) SWIGTYPE "new $&csclassname($iminput, false)"
|
||||
%{ $input = (void *)new $1_ltype((const $1_ltype &)$1); %}
|
||||
%typemap(csdirectorin) SWIGTYPE "new $&csclassname($iminput, true)"
|
||||
%typemap(csdirectorout) SWIGTYPE "$&csclassname.getCPtr($cscall).Handle"
|
||||
|
||||
/* Generic pointers and references */
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@
|
|||
$*csclassname ret = (cPtr == global::System.IntPtr.Zero) ? null : new $*csclassname(cPtr, $owner);$excode
|
||||
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 *, 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)"
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@
|
|||
#endif
|
||||
|
||||
%typemap(directorin) SWIGTYPE
|
||||
"$input = (void *)&$1;"
|
||||
"$input = (void *)new $1_ltype((const $1_ltype &)$1);"
|
||||
%typemap(directorout) SWIGTYPE
|
||||
%{ if (!$input) {
|
||||
SWIG_DSetPendingException(SWIG_DIllegalArgumentException, "Unexpected null return for type $1_type");
|
||||
|
|
@ -65,7 +65,7 @@
|
|||
}
|
||||
$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(din) SWIGTYPE "$&dclassname.swigGetCPtr($dinput)"
|
||||
|
|
|
|||
|
|
@ -584,7 +584,7 @@
|
|||
%typemap(goout) SWIGTYPE ""
|
||||
|
||||
%typemap(directorin) SWIGTYPE
|
||||
%{ $input = ($&1_ltype)&$1; %}
|
||||
%{ $input = new $1_ltype((const $1_ltype &)$1); %}
|
||||
|
||||
%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
|
||||
%{ $input = 0;
|
||||
*(($&1_ltype*)&$input) = &$1; %}
|
||||
%typemap(javadirectorin) SWIGTYPE "new $&javaclassname($jniinput, false)"
|
||||
*(($&1_ltype*)&$input) = new $1_ltype((const $1_ltype &)$1); %}
|
||||
%typemap(javadirectorin) SWIGTYPE "new $&javaclassname($jniinput, true)"
|
||||
%typemap(javadirectorout) SWIGTYPE "$&javaclassname.getCPtr($javacall)"
|
||||
|
||||
/* Generic pointers and references */
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@
|
|||
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 *, CTYPE [] "($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(directorin,descriptor="L$packagepath/$&javainterfacename;") CTYPE
|
||||
%{ $input = 0;
|
||||
*(($&1_ltype*)&$input) = &$1; %}
|
||||
*(($&1_ltype*)&$input) = new $1_ltype((const $1_ltype &)$1); %}
|
||||
%typemap(directorin,descriptor="L$packagepath/$javainterfacename;") CTYPE *, CTYPE []
|
||||
%{ *(($&1_ltype)&$input) = ($1_ltype) $1; %}
|
||||
%typemap(directorin,descriptor="L$packagepath/$javainterfacename;") CTYPE &
|
||||
|
|
|
|||
|
|
@ -429,7 +429,7 @@
|
|||
|
||||
%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 "";
|
||||
|
|
|
|||
|
|
@ -415,7 +415,7 @@
|
|||
}
|
||||
|
||||
%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 & {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue