Fix Java swigReleaseOwnership() and swigTakeOwnership() regression

Fixes segfault when using non-director classes.
Restores a dynamic_cast which was previously removed.
The dynamic_cast is not needed for the swig_connect_director call ...
we'll have to find another solution for #449 for Java.

Closes #1184
This commit is contained in:
William S Fulton 2018-03-09 08:13:41 +00:00
parent 3ce3ce0683
commit b4f4ce4fd5
5 changed files with 125 additions and 5 deletions

View File

@ -7,6 +7,10 @@ the issue number to the end of the URL: https://github.com/swig/swig/issues/
Version 4.0.0 (in progress)
===========================
2018-03-09: fultonwi
[Java] #1184 Fix swigReleaseOwnership() and swigTakeOwnership() regression
for non-director classes. Restores a dynamic_cast which was previously removed.
2018-03-07: llongi
Github PR #1166 - Fix preprocessor handling of macros with commas
in a // comment.

View File

@ -194,6 +194,7 @@ CPP_TEST_CASES += \
director_nspace_director_name_collision \
director_overload \
director_overload2 \
director_ownership \
director_pass_by_value \
director_primitives \
director_property \

View File

@ -0,0 +1,72 @@
%module(directors="1") director_ownership
// Github issue #1184
%include "std_string.i"
%feature("director") example::ContentBase;
%feature("director") example::ContentDerived;
%newobject example::make_content;
%inline %{
#include <string>
namespace example
{
class ContentBase
{
public:
ContentBase() {}
virtual ~ContentBase() {}
virtual std::string get_name() const = 0;
};
class ContentDerived: public ContentBase
{
public:
ContentDerived():ContentBase() { m_name = "ContentDerived"; }
virtual ~ContentDerived() {}
virtual std::string get_name() const override { return m_name; }
private:
std::string m_name;
};
class Container
{
public:
Container() { m_content = 0; }
~Container()
{
clear_content();
}
// the container takes the ownership of the content
void set_content(ContentBase* content)
{
clear_content();
m_content = content;
}
ContentBase* get_content() { return m_content; }
private:
void clear_content()
{
if(m_content)
{
delete m_content;
m_content = 0;
}
}
private:
ContentBase* m_content;
};
static ContentBase* make_content() { return new ContentDerived(); }
} // namespace example
%}

View File

@ -0,0 +1,42 @@
import director_ownership.*;
public class director_ownership_runme {
static {
try {
System.loadLibrary("director_ownership");
} 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);
}
}
public static void set_content_and_release(Container container, ContentBase content) {
content.swigReleaseOwnership();
container.set_content(content);
}
public static void main(String argv[]) {
Container container = new Container();
// make a content in java (cMemoryOwn true)
ContentBase content_java = new ContentDerived();
// make a content in c++ (cMemoryOwn true)
ContentBase content_cpp = director_ownership.make_content();
set_content_and_release(container, content_java);
if (!container.get_content().get_name().equals("ContentDerived"))
throw new RuntimeException("did not get ContentDerived");
// when swigReleaseOwnership() is called on content_cpp, swig tries a static_cast to director and calls the method
// director->swig_java_change_ownership. The content created in c++ native library is not a director, therefore a
// segfault may occur.
// With a check done using dynamic_cast this issue could be avoided.
set_content_and_release(container, content_cpp);
if (!container.get_content().get_name().equals("ContentDerived"))
throw new RuntimeException("did not get ContentDerived");
}
}

View File

@ -3763,15 +3763,16 @@ public:
Printf(code_wrap->code, " %s *obj = *((%s **)&objarg);\n", smartptr, smartptr);
Printf(code_wrap->code, " // Keep a local instance of the smart pointer around while we are using the raw pointer\n");
Printf(code_wrap->code, " // Avoids using smart pointer specific API.\n");
Printf(code_wrap->code, " %s *director = static_cast<%s *>(obj->operator->());\n", dirClassName, dirClassName);
}
else {
Printf(code_wrap->code, " %s *director = dynamic_cast<%s *>(obj->operator->());\n", dirClassName, dirClassName);
} else {
Printf(code_wrap->code, " %s *obj = *((%s **)&objarg);\n", norm_name, norm_name);
Printf(code_wrap->code, " %s *director = static_cast<%s *>(obj);\n", dirClassName, dirClassName);
Printf(code_wrap->code, " %s *director = dynamic_cast<%s *>(obj);\n", dirClassName, dirClassName);
}
Printf(code_wrap->code, " (void)jcls;\n");
Printf(code_wrap->code, " director->swig_java_change_ownership(jenv, jself, jtake_or_release ? true : false);\n");
Printf(code_wrap->code, " if (director) {\n");
Printf(code_wrap->code, " director->swig_java_change_ownership(jenv, jself, jtake_or_release ? true : false);\n");
Printf(code_wrap->code, " }\n");
Printf(code_wrap->code, "}\n");
Wrapper_print(code_wrap, f_wrappers);