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

Popular posts from this blog

Ansible - ERROR! the field 'hosts' is required but was not set -

customize file_field button ruby on rails -

SoapUI on windows 10 - high DPI/4K scaling issue -