title: Correct way to interact with arrays using SWIG
body: <p>I'm a bit lost with typemaps in swig and how to use arrays. I have prepared a working example that uses arrays between java and c using swig, but i don't know if it is the correct way to do it.</p>
  
  <p>Basically i want to pass a byte array <code>byte[]</code> from java to c as a ´signed char *` + it's size, modify it in c and see the changes in java and create an array in c and use it in Java.</p>
  
  <p>I have take a look at theese questions:
  <a href="https://stackoverflow.com/questions/10947560/how-to-pass-arrayarray-of-long-in-java-from-java-to-c-using-swig">How to pass array(array of long in java) from Java to C++ using Swig</a>, 
  <a href="https://stackoverflow.com/questions/11584599/pass-an-array-to-a-wrapped-function-as-pointersize-or-range/11584600#11584600">Pass an array to a wrapped function as pointer+size or range</a>, 
  <a href="https://stackoverflow.com/questions/2740068/how-can-i-make-swig-correctly-wrap-a-char-buffer-that-is-modified-in-c-as-a-jav">How can I make Swig correctly wrap a char* buffer that is modified in C as a Java Something-or-other?</a></p>
  
  <p>And in fact used the solutions as a guide to make the example.</p>
  
  <p>This is my code in the file arrays.h:</p>
  
  <pre><code>#include &lt;iostream&gt;
  
  bool createArray(signed char ** arrCA, int * lCA){
      *lCA = 10;
      *arrCA = (signed char*) calloc(*lCA, sizeof(signed char));
  
      for(int i = 0; i &lt; *lCA; i++){
          (*arrCA)[i] = i;
      }
  
      return *arrCA != NULL;
  }
  
  bool readArray(const signed char arrRA[], const int lRA){
      for(int i = 0; i &lt; lRA; i++){
          std::cout &lt;&lt; ((unsigned int) arrRA[i]) &lt;&lt; " ";
      }
      std::cout &lt;&lt; std::endl;
      return true;
  }
  
  bool modifyArrayValues(signed char arrMA[], const int lMA){
      for(int i = 0; i &lt; lMA; i++){
          arrMA[i] = arrMA[i] * 2;
      }
      return true;
  }
  
  
  bool modifyArrayLength(signed char arrMALIn[], int lMALIn, signed char ** arrMALOut, int * lMALOut){
  
      *lMALOut = 5;
      *arrMALOut = (signed char*) calloc(*lMALOut, sizeof(signed char));
  
      for(int i = 0; i &lt; *lMALOut; i++){
          (*arrMALOut)[i] = arrMALIn[i];
      }
      return true;
  }
  </code></pre>
  
  <p>This is the .i file for swig (arrays.i):</p>
  
  <pre><code>%module arrays
  
  %{
      #include "arrays.h"
  %}
  
  %typemap(jtype) bool createArray "byte[]"
  %typemap(jstype) bool createArray "byte[]"
  %typemap(jni) bool createArray "jbyteArray"
  %typemap(javaout) bool createArray { return $jnicall; }
  %typemap(in, numinputs=0) signed char ** arrCA (signed char * temp) "$1=&amp;temp;"
  %typemap(in, numinputs=0) int * lCA (int l) "$1=&amp;l;"
  %typemap(argout) (signed char ** arrCA, int * lCA) {
      $result = JCALL1(NewByteArray, jenv, *$2);
      JCALL4(SetByteArrayRegion, jenv, $result, 0, *$2, (const jbyte*) *$1);
  }
  %typemap(out) bool createArray {
      if (!$1) {
          return NULL;
      }
  }
  
  
  %typemap(jtype) (const signed char arrRA[], const int lRA) "byte[]"
  %typemap(jstype) (const signed char arrRA[], const int lRA) "byte[]"
  %typemap(jni) (const signed char arrRA[], const int lRA) "jbyteArray"
  %typemap(javain) (const signed char arrRA[], const int lRA) "$javainput"
  
  %typemap(in,numinputs=1) (const signed char arrRA[], const int lRA) {
    $1 = JCALL2(GetByteArrayElements, jenv, $input, NULL);
    $2 = JCALL1(GetArrayLength, jenv, $input);
  }
  
  %typemap(freearg) (const signed char arrRA[], const int lRA) {
    // Or use  0 instead of ABORT to keep changes if it was a copy
    JCALL3(ReleaseByteArrayElements, jenv, $input, $1, JNI_ABORT); 
  }
  
  
  %typemap(jtype) (signed char arrMA[], const int lMA) "byte[]"
  %typemap(jstype) (signed char arrMA[], const int lMA) "byte[]"
  %typemap(jni) (signed char arrMA[], const int lMA) "jbyteArray"
  %typemap(javain) (signed char arrMA[], const int lMA) "$javainput"
  
  %typemap(in, numinputs=1) (signed char arrMA[], const int lMA) {
      $1 = JCALL2(GetByteArrayElements, jenv, $input, NULL);
      $2 = JCALL1(GetArrayLength, jenv, $input);
  }
  
  %typemap(freearg) (signed char arrMA[], const int lMA) {
    JCALL3(ReleaseByteArrayElements, jenv, $input, $1, 0); 
  } 
  
  %typemap(jtype) (signed char arrMALIn[], int lMALIn) "byte[]"
  %typemap(jstype) (signed char arrMALIn[], int lMALIn) "byte[]"
  %typemap(jni) (signed char arrMALIn[], int lMALIn) "jbyteArray"
  %typemap(javain) (signed char arrMALIn[], int lMALIn) "$javainput"
  
  %typemap(in, numinputs=1) (signed char arrMALIn[], int lMALIn) {
      $1 = JCALL2(GetByteArrayElements, jenv, $input, NULL);
      $2 = JCALL1(GetArrayLength, jenv, $input);
  }
  
  %typemap(freearg) (signed char arrMALIn[], int lMALIn) {
      JCALL3(ReleaseByteArrayElements, jenv, $input, $1, JNI_ABORT); 
  }
  
  %typemap(jtype) bool modifyArrayLength "byte[]"
  %typemap(jstype) bool modifyArrayLength "byte[]"
  %typemap(jni) bool modifyArrayLength "jbyteArray"
  %typemap(javaout) bool modifyArrayLength { return $jnicall; }
  %typemap(in, numinputs=0) signed char ** arrMALOut (signed char * temp) "$1=&amp;temp;"
  %typemap(in, numinputs=0) int * lMALOut (int l) "$1=&amp;l;"
  %typemap(argout) (signed char ** arrMALOut, int * lMALOut) {
      $result = JCALL1(NewByteArray, jenv, *$2);
      JCALL4(SetByteArrayRegion, jenv, $result, 0, *$2, (const jbyte*) *$1);
  }
  %typemap(out) bool modifyArrayLength {
      if (!$1) {
          return NULL;
      }
  }
  
  
  %include "arrays.h"
  </code></pre>
  
  <p>And finally the Java code to test it:</p>
  
  <pre><code>public class Run{
  
      static {
          System.loadLibrary("Arrays");
      }
  
      public static void main(String[] args){
  
          byte[] test = arrays.createArray();
  
          printArray(test);       
  
          arrays.readArray(test);
  
          arrays.modifyArrayValues(test);
  
          printArray(test);
  
          byte[] test2 = arrays.modifyArrayLength(test);
  
          printArray(test2);
  
      }
  
      private static void printArray(byte[] arr){
  
          System.out.println("Array ref: " + arr);
  
          if(arr != null){
              System.out.println("Array length: " + arr.length);
  
              System.out.print("Arrays items: ");
  
              for(int i =0; i &lt; arr.length; i++){
                  System.out.print(arr[i] + " ");
              }
          }
          System.out.println();
      }
  }
  </code></pre>
  
  <p>The example works, but I'm not sure that that is the correct way, i mean:</p>
  
  <p>is there an easier way to achieve the same result?</p>
  
  <p>does this code have memory leaks (on one hand i think there is because i do a calloc but i don't free it, but on the other hand i pass it to the SetByteArrayRegion, so maybe freeing it would cause an error)?</p>
  
  <p>does the SetByteArrayRegion copy the values or only the reference?, for example if instead of actually doing a calloc what if obtaining an array from an c++ object by reference that is going to be destroy when it exits scope?</p>
  
  <p>is the array returned to Java correctly freed when nullifying it?</p>
  
  <p>is there a way to specify from where to where a typemap applies?, i mean, in the .i code i have provided a typemap for each function, where i think i could reuse some of them, but if there were others functions with same parameters that i don't want to typemap them, how can i do that, i may not be able to modify the parameters name of the functions.</p>
  
  <p>I have seen the carrays.i possibility described in this question <a href="https://stackoverflow.com/questions/4167233/how-do-i-pass-arrays-from-java-to-c-using-swig">How do I pass arrays from Java to C++ using Swig?</a>, but that implies that if the size of the array is 1000 items and i want to send it through a Java Socket or create a String from it, i have to make 1 JNI Call for each array item. And i actually want a <strong><code>byte[]</code></strong> in the Java side, not a set of functions to access the underlaying array, so already existing code works without modifications.</p>
  
  <hr>
  
  <p>Context:
  The reason i want to achieve this is that there is a library that have some functionality, but the important part here is that it allows to import and export data from the library making use of the Google Protocols Buffers. So the code related to this question looks like this:</p>
  
  <pre><code>class SomeLibrary {
  
    bool export(const std::string &amp; sName, std::string &amp; toExport);
  
    bool import(const std::string &amp; sName, const std::string &amp; toImport);
  
  }
  </code></pre>
  
  <p>The thing is that Protobuf in C++ uses std::string to store the data, but this data is binary so it can not be returned as a normal Java String because it gets truncated, more of this in <a href="https://stackoverflow.com/questions/12192624/swig-convert-return-type-stdstringbinary-to-java-byte/12196522#comment16788430_12196522">Swig: convert return type std::string(binary) to java byte[]</a>.</p>
  
  <p>So my idea is to return to Java a <code>byte[]</code> for the serialized Protobuf (as does the Java version of Protocol buffers) and accept <code>byte[]</code> for parsing protobufs. To avoid getting <code>SWIGTYPE_p_std_string</code> in the second argument of the export, and having String for the second argument of import y have wrapped both functions using %extend, like this:</p>
  
  <pre><code>%extend SomeLibrary{
  
    bool export(const std::string &amp; sName, char ** toExportData, int * toExportLength);
  
    bool import(const std::string &amp; sName, char * toImportData, int toImportLength);
  
  }
  </code></pre>
  
  <p>And now i should be able to make the typemaps.</p>
  
  <p>But in order to be more general, i asked for the general of manipulating arrays from Java to SWIG, <strong>having</strong> the native Java <code>byte[]</code>.</p>