Modifications to the typemaps giving users fine control over memory ownership and lifetime of director classes. Patch from Scott Michel.

git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk/SWIG@7070 626c5289-ae23-0410-ae9c-e8d60b6d4f22
This commit is contained in:
William S Fulton 2005-03-15 21:31:31 +00:00
commit 17f65da214
3 changed files with 269 additions and 143 deletions

View file

@ -12,57 +12,126 @@
#ifdef __cplusplus
#if defined(DEBUG_DIRECTOR_OWNED)
#include <iostream>
#endif
namespace Swig {
/* Java object wrapper */
class JObjectWrapper {
public:
JObjectWrapper() : jthis_(NULL), weak_global_(true) {
}
~JObjectWrapper() {
jthis_ = NULL;
weak_global_ = true;
}
bool set(JNIEnv *jenv, jobject jobj, bool mem_own, bool weak_global) {
if (jthis_ == NULL) {
weak_global_ = weak_global;
if (jobj)
jthis_ = ((weak_global_ || !mem_own) ? jenv->NewWeakGlobalRef(jobj) : jenv->NewGlobalRef(jobj));
#if defined(DEBUG_DIRECTOR_OWNED)
std::cout << "JObjectWrapper::set(" << jobj << ", " << (weak_global ? "weak_global" : "global_ref") << ") -> " << jthis_ << std::endl;
#endif
return true;
} else {
#if defined(DEBUG_DIRECTOR_OWNED)
std::cout << "JObjectWrapper::set(" << jobj << ", " << (weak_global ? "weak_global" : "global_ref") << ") -> already set" << std::endl;
#endif
return false;
}
}
jobject get(JNIEnv *jenv) const {
#if defined(DEBUG_DIRECTOR_OWNED)
std::cout << "JObjectWrapper::get(";
if (jthis_)
std::cout << jthis_;
else
std::cout << "null";
std::cout << ") -> return new local ref" << std::endl;
#endif
return (jthis_ ? jenv->NewLocalRef(jthis_) : jthis_);
}
void release(JNIEnv *jenv) {
#if defined(DEBUG_DIRECTOR_OWNED)
std::cout << "JObjectWrapper::release(" << jthis_ << "): " << (weak_global_ ? "local ref" : "global ref") << std::endl;
#endif
if (weak_global_)
jenv->DeleteWeakGlobalRef(jthis_);
else
jenv->DeleteGlobalRef(jthis_);
jthis_ = NULL;
weak_global_ = true;
}
jobject peek() {
return jthis_;
}
private:
/* pointer to Java object */
jobject jthis_;
/* Local or global reference flag */
bool weak_global_;
};
/* director base class */
class Director {
private:
/* pointer to Java virtual machine */
JavaVM *swig_jvm;
private:
/* pointer to Java virtual machine */
JavaVM *swig_jvm_;
protected:
/* pointer to the wrapped Java object */
jobject swig_self;
protected:
/* Java object wrapper */
JObjectWrapper swig_self_;
/* Acquire Java VM environment from Java VM */
JNIEnv *swig_acquire_jenv() const {
JNIEnv *env = NULL;
swig_jvm->AttachCurrentThread((void **) &env, NULL);
return env;
}
/* Acquire Java VM environment from Java VM */
JNIEnv *swig_acquire_jenv() const {
JNIEnv *env = NULL;
swig_jvm_->AttachCurrentThread((void **) &env, NULL);
return env;
}
/* Disconnect director from Java object */
void swig_disconnect_director_self(const char *disconn_method) {
if (swig_self) {
JNIEnv *jenv = swig_acquire_jenv();
jmethodID disconn_meth = jenv->GetMethodID(jenv->GetObjectClass(swig_self), disconn_method, "()V");
if (disconn_meth) {
jenv->CallVoidMethod(swig_self, disconn_meth);
} else {
jenv->ExceptionClear();
}
jenv->DeleteGlobalRef(swig_self);
swig_self = (jobject) NULL;
/* Disconnect director from Java object */
void swig_disconnect_director_self(const char *disconn_method) {
JNIEnv *jenv = swig_acquire_jenv();
jobject jobj = swig_self_.get(jenv);
#if defined(DEBUG_DIRECTOR_OWNED)
std::cout << "Swig::Director::disconnect_director_self(" << jobj << ")" << std::endl;
#endif
if (jobj) {
jmethodID disconn_meth = jenv->GetMethodID(jenv->GetObjectClass(jobj), disconn_method, "()V");
if (disconn_meth) {
jenv->CallVoidMethod(jobj, disconn_meth);
} else {
jenv->ExceptionClear();
}
}
}
public:
Director(JNIEnv *jenv) : swig_jvm((JavaVM *) NULL), swig_self(NULL) {
/* Acquire the Java VM pointer */
jenv->GetJavaVM(&swig_jvm);
}
public:
Director(JNIEnv *jenv) : swig_jvm_((JavaVM *) NULL), swig_self_() {
/* Acquire the Java VM pointer */
jenv->GetJavaVM(&swig_jvm_);
}
virtual ~Director() {
}
virtual ~Director() {
swig_self_.release(swig_acquire_jenv());
}
/* Set swig_self and get Java global reference on object */
void swig_set_self(JNIEnv *jenv, jobject jself) {
swig_self = jenv->NewGlobalRef(jself);
}
bool swig_set_self(JNIEnv *jenv, jobject jself, bool mem_own, bool weak_global) {
return swig_self_.set(jenv, jself, mem_own, weak_global);
}
/* return a pointer to the wrapped Java object */
jobject swig_get_self() const {
return swig_self;
}
jobject swig_get_self(JNIEnv *jenv) const {
return swig_self_.get(jenv);
}
};
}

View file

@ -891,34 +891,43 @@
%typemap(javaimports) SWIGTYPE, SWIGTYPE *, SWIGTYPE &, SWIGTYPE [], SWIGTYPE (CLASS::*) ""
%typemap(javainterfaces) SWIGTYPE, SWIGTYPE *, SWIGTYPE &, SWIGTYPE [], SWIGTYPE (CLASS::*) ""
// Proxy classes (base classes, ie, not derived classes)
%typemap(javabody) SWIGTYPE %{
/* javabody typemaps */
%define SWIG_JAVABODY_METHODS(PTRCTOR_VISIBILITY, CPTR_VISIBILITY, TYPENAME...)
// Base proxy classes
%typemap(javabody) TYPENAME %{
private long swigCPtr;
protected boolean swigCMemOwn;
protected $javaclassname(long cPtr, boolean cMemoryOwn) {
PTRCTOR_VISIBILITY $javaclassname(long cPtr, boolean cMemoryOwn) {
swigCMemOwn = cMemoryOwn;
swigCPtr = cPtr;
}
protected static long getCPtr($javaclassname obj) {
CPTR_VISIBILITY static long getCPtr($javaclassname obj) {
return (obj == null) ? 0 : obj.swigCPtr;
}
%}
// Derived proxy classes
%typemap(javabody_derived) SWIGTYPE %{
%typemap(javabody_derived) TYPENAME %{
private long swigCPtr;
protected $javaclassname(long cPtr, boolean cMemoryOwn) {
PTRCTOR_VISIBILITY $javaclassname(long cPtr, boolean cMemoryOwn) {
super($moduleJNI.SWIG$javaclassnameUpcast(cPtr), cMemoryOwn);
swigCPtr = cPtr;
}
protected static long getCPtr($javaclassname obj) {
CPTR_VISIBILITY static long getCPtr($javaclassname obj) {
return (obj == null) ? 0 : obj.swigCPtr;
}
%}
%enddef
/* Set the default for SWIGTYPE: pointer constructor is protected,
getCPtr is protected. Season to your own taste! */
SWIG_JAVABODY_METHODS(protected, protected, SWIGTYPE)
// Typewrapper classes
%typemap(javabody) SWIGTYPE *, SWIGTYPE &, SWIGTYPE [], SWIGTYPE (CLASS::*) %{
@ -943,14 +952,49 @@
}
%}
%typemap(javaconstruct) SWIGTYPE {
this($imcall, true);
}
/*
* Java constructor typemaps:
*
* The javaconstruct and javaconstruct_director typemaps are inserted when a
* proxy class's constructor is generated. These typemaps allow control over what
* code is executed in the constructor as well as specifying who owns the
* underlying C/C++ object. Normally, Java has ownership and the underlying
* C/C++ object is deallocated when the Java object is finalized (swigCMemOwn
* is true.) If swigCMemOwn is false, C/C++ is ultimately responsible for
* deallocating the underlying object's memory.
*
* The SWIG_PROXY_CONSTRUCTOR and SWIG_DIRECTOR_CONSTRUCTOR macros define the
* javaconstruct and javaconstruct_director typemaps for a proxy class for a
* particular TYPENAME. OWNERSHIP is passed as the value of swigCMemOwn to the
* pointer constructor method. SWIG_DIRECTOR_CONSTRUCTOR takes an additional
* parameter, WEAKREF, that determines which kind of Java object reference
* will be used by the C++ director class (WeakGlobalRef vs. GlobalRef.)
*
* The SWIG_DIRECTOR_OWNED macro sets the ownership of director-based proxy
* classes to false, meaning that the underlying C++ object will be
* reclaimed by C++.
*/
%typemap(javaconstruct_director) SWIGTYPE {
this($imcall, true);
$moduleJNI.$javaclassname_director_connect(this, swigCPtr);
%define SWIG_PROXY_CONSTRUCTOR(OWNERSHIP, TYPENAME...)
%typemap(javaconstruct) TYPENAME {
this($imcall, OWNERSHIP);
}
%enddef
%define SWIG_DIRECTOR_CONSTRUCTOR(OWNERSHIP, WEAKREF, TYPENAME...)
%typemap(javaconstruct_director) TYPENAME {
this($imcall, OWNERSHIP);
$moduleJNI.$javaclassname_director_connect(this, swigCPtr, OWNERSHIP, WEAKREF);
}
%enddef
%define SWIG_DIRECTOR_OWNED(TYPENAME...)
SWIG_DIRECTOR_CONSTRUCTOR(true, false, TYPENAME)
%enddef
// Set the default for SWIGTYPE: Java owns the C/C++ object.
SWIG_PROXY_CONSTRUCTOR(true, SWIGTYPE)
SWIG_DIRECTOR_CONSTRUCTOR(true, true, SWIGTYPE)
%typemap(javadestruct, methodname="delete") SWIGTYPE {
if(swigCPtr != 0 && swigCMemOwn) {