java - Using SWIG for setting types in overloaded C++ method -
i writing c++ library used applications on different platforms, including android. , android build swig used (i cannot change choice, , have never worked swig). automatic type conversion java-to-c++ worked fine until assigned task of init method overloading.
for old init
c++ interface is:
/** * initialize classifier file * @param modelpath std::string full path file model * @return classifier possible values: * pointer classifier instance in case of success * nullptr otherwise */ static classifier* init(const std::string& modelpath);
the following code generating:
public static classifier init(string modelpath) { long cptr = cljni.classifier_init__swig_0(modelpath); return (cptr == 0) ? null : new classifier(cptr, true); }
for new init
c++ is:
/** * initialize classifier memory block * @param modelmemory char* pointer memory block model definition stored * @param modelmemorysize size_t size of memory block allocated model storage * @return classifier possible values: * pointer classifier instance in case of success * nullptr otherwise */ static classifier* init(char* modelmemory, const size_t modelmemorysize);
and java code generated swig is:
public static classifier init(string modelmemory, long modelmemorysize) { long cptr = cljni.classifier_init__swig_1(modelmemory, modelmemorysize); return (cptr == 0) ? null : new classifier(cptr, true); }
but need java method as:
classifier init(byte[] modelmemory, long modelmemorysize);
i.e. char*
have converted byte[]
instead of string
.
what changes should in classifier.i file (that looks follows) have 2 init
methods available call java?
%{ #include "group.h" #include "classifier.h" %} //java programmers afraid of 'delete' method, have rename it. //yes, bloody stupid, know. %typemap(javadestruct, methodname="dispose", methodmodifiers="public synchronized") cl::classifier { if(swigcptr != 0 && swigcmemown) { swigcmemown = false; $jnicall; } swigcptr = 0; } %typemap(javafinalize) cl::classifier %{ protected void finalize() { dispose(); } %} %newobject cl::classifier::init; %include "classifier.h"
the following solution (based on flexo's example) checked on swig 2.0.11 , swig 3.0.8:
%module classifier %{ #include "group.h" #include "classifier.h" %} %typemap(jtype) (signed char* modelmemory, const size_t modelmemorysize) "byte[]" %typemap(jstype) (signed char* modelmemory, const size_t modelmemorysize) "byte[]" %typemap(jni) (signed char* modelmemory, const size_t modelmemorysize) "jbytearray" %typemap(javain) (signed char* modelmemory, const size_t modelmemorysize) "$javainput" %typemap(in,numinputs=1) (signed char* modelmemory, const size_t modelmemorysize) { $1 = jcall2(getbytearrayelements, jenv, $input, null); $2 = jcall1(getarraylength, jenv, $input); } %typemap(freearg) (signed char* modelmemory, const size_t modelmemorysize) { // or use 0 instead of abort keep changes if copy jcall3(releasebytearrayelements, jenv, $input, $1, jni_abort); } %typemap(javadestruct, methodname="dispose", methodmodifiers="public synchronized") cl::classifier { if(swigcptr != 0 && swigcmemown) { swigcmemown = false; $jnicall; } swigcptr = 0; } %typemap(javafinalize) cl::classifier %{ protected void finalize() { dispose(); } %} %newobject cl::classifier::init; %include "classifier.h"
%include "arrays_java.i"
, %apply
(written in original example) found unnecessary.
this works , provides 2 init
methods:
public static classifier init(string modelpath) { long cptr = cljni.classifier_init__swig_0(modelpath); return (cptr == 0) ? null : new classifier(cptr, true); } public static classifier init(byte[] modelmemory) { long cptr = cljni.classifier_init__swig_1(modelmemory); return (cptr == 0) ? null : new classifier(cptr, true); }
but requires usage of signed char*
type instead of char*
. otherwise
public static classifier init(string modelmemory, long modelmemorysize)
is produced.
also have found swig 3.0.8 solution can in 1 line:
%apply(char *string, size_t length) { (signed char *modelmemory, size_t modelmemorysize) };
i.e. classifier.i is:
%module classifier %{ #include "group.h" #include "classifier.h" %} %apply(char *string, size_t length) { (signed char *modelmemory, size_t modelmemorysize) }; %typemap(javadestruct, methodname="dispose", methodmodifiers="public synchronized") cl::classifier { if(swigcptr != 0 && swigcmemown) { swigcmemown = false; $jnicall; } swigcptr = 0; } %typemap(javafinalize) cl::classifier %{ protected void finalize() { dispose(); } %} %newobject cl::classifier::init; %include "classifier.h"
with swig 2.0.11 way leads compilation error because incorrect wrapper (cljava_wrap.cxx) generation:
swigexport jlong jnicall java_impl_tools_cljni_classifier_1init_1_1swig_11(jnienv *jenv, jclass jcls, jbytearray jarg1) { jlong jresult = 0 ; signed char *arg1 = (signed char *) 0 ; size_t arg2 ; cl::classifier *result = 0 ; (void)jenv; (void)jcls; { if (jarg1) { arg1 = (char *) jenv->getbytearrayelements(jarg1, 0); // error here: invalid conversion 'char*' 'signed char*' arg2 = (size_t) jenv->getarraylength(jarg1); } else { arg1 = 0; arg2 = 0; } } result = (cl::classifier *)cl::classifier::init(arg1,arg2); *(cl::classifier **)&jresult = result; { if (jarg1) jenv->releasebytearrayelements(jarg1, (jbyte *)arg1, 0); } return jresult; }
Comments
Post a Comment