|
From: Michael P. <puj...@la...> - 2007-06-09 13:17:56
|
Hi
I'm binding a C++ lib to Java and to make the bindings more Java
friendly, I want to map some C++ container classes
to corresponding idiomatic Java container classes. (a bit like
std::string <=> Java.lang.String mapping, but for custom classes)
Here's the function for which I want to generate wrappers:
void dispatch_refresh(const pfc::list_base_const_t<metadb_handle_ptr> &
p_list);
I want to map "const pfc::list_base_const_t<metadb_handle_ptr> &" to
Java type "java.util.Vector<metadb_handle>", so I wrote this interface file
(note that list_t is a subclass of pure abstract class list_base_const_t)
/////////////////////////////////////////////////////////////
%module test
%{
/* Includes the header in the wrapper code */
/* convert Vector<metadb_handle> to pfc::list_t<metadb_handle_ptr> */
static pfc::list_t<metadb_handle_ptr> * metadb_vector_to_list(JNIEnv
*jenv, jobject vector) {
jclass vector_class = jenv->FindClass("java/util/Vector");
jmethodID vector_get_method = jenv->GetMethodID(vector_class, "get",
"(I)Ljava/lang/Object;");
jmethodID vector_size_method = jenv->GetMethodID(vector_class,
"size", "()I");
jclass metadb_handle_class = jenv->FindClass("metadb_handle");
jfieldID metadb_handle_cptr_field =
jenv->GetFieldID(metadb_handle_class, "swigCPtr", "J");
int size = jenv->CallIntMethod(vector, vector_size_method);
pfc::list_t<metadb_handle_ptr> *list = new
pfc::list_t<metadb_handle_ptr>();
int i;
for(i = 0 ; i < size ; i++) {
jobject elem = jenv->CallObjectMethod(vector, vector_get_method, i);
metadb_handle_ptr item = metadb_handle_ptr((metadb_handle
*)jenv->GetLongField(elem, metadb_handle_cptr_field));
list->add_item(item);
}
return list;
}
void dispatch_refresh(const pfc::list_base_const_t<metadb_handle_ptr> &
p_list) {
}
%}
%typemap(jni) const pfc::list_base_const_t<metadb_handle_ptr> & "jobject"
%typemap(jtype) const pfc::list_base_const_t<metadb_handle_ptr> & "Vector"
%typemap(jstype) const pfc::list_base_const_t<metadb_handle_ptr> & "Vector"
%typemap(in) const pfc::list_base_const_t<metadb_handle_ptr> &
%{ if(!$input) {
SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "null");
return $null;
}
$1 = metadb_vector_to_list(jenv, $input);
%}
%typemap(javain) const pfc::list_base_const_t<metadb_handle_ptr> &
"$javainput"
%typemap(javaout) const pfc::list_base_const_t<metadb_handle_ptr> & {
return $jnicall;
}
%typemap(throws) const pfc::list_base_const_t<metadb_handle_ptr> &
%{ SWIG_JavaThrowException(jenv, SWIG_JavaRuntimeException, "yop");
return $null; %}
void dispatch_refresh(const pfc::list_base_const_t<metadb_handle_ptr> &
p_list);
/////////////////////////////////////////////////////////////
I case you wonder were the vector arg of metadb_vector_to_list() comes
from,
I have a reciprocal function of metadb_vector_to_list() that is not call
through SWIG
but using JNI Invocation API and instantiating Java SWIG proxy classes
from C++ (had to
make the constructor taking in argument object's pointer public for this
to work).
The interface file generates the following dispatch_refresh wrapper
code, which compiles just fine:
SWIGEXPORT void JNICALL Java_testJNI_dispatch_1refresh(JNIEnv *jenv,
jclass jcls, jobject jarg1) {
pfc::list_base_const_t<metadb_handle_ptr > *arg1 = 0 ;
(void)jenv;
(void)jcls;
if(!jarg1) {
SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "null");
return ;
}
/*
const char *arg1_pstr = (const char
*)jenv->GetStringUTFChars(jarg1, 0);
if (!arg1_pstr) return ;
std::string arg1_str(arg1_pstr);
arg1 = &arg1_str;
jenv->ReleaseStringUTFChars(jarg1, arg1_pstr);
*/
arg1 = metadb_vector_to_list(jenv, jarg1);
dispatch_refresh((pfc::list_base_const_t<metadb_handle_ptr > const
&)*arg1);
}
The problem is that metadb_vector_to_list() allocates a list_t object
that should be freed after the call to dispatch_refresh() using "delete
arg1;".
To solve it:
- is there a way to insert arbitrary code after dispatch_refresh(), in
that case to free arg1
- is there a way to have arg1 not a pointer ? that way if the original
func is defined as
void dispatch_refresh(const pfc::list_t<metadb_handle_ptr> & p_list);
and metadb_vector_to_list() return a list_t instead of a lis_t *, the
generated could look like:
SWIGEXPORT void JNICALL Java_testJNI_dispatch_1refresh(JNIEnv *jenv,
jclass jcls, jobject jarg1) {
pfc::list_t<metadb_handle_ptr > arg1;
(void)jenv;
(void)jcls;
if(!jarg1) {
SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, "null");
return ;
}
arg1 = metadb_vector_to_list(jenv, jarg1);
dispatch_refresh(arg1);
}
|