I got a little lost with typemaps in swig and how to use arrays. I prepared a working example that uses arrays between java and c with swig, but I don't know if this is the right thing to do.
Basically, I want to transfer an array of bytes byte[]from java to c as aign char * `+ its size, change it in c and see the changes in java and create an array in c and use it in Java.
I will consider these issues:
How to transfer an array (long array in java) from Java to C ++ using Swig ,
Pass the array to the wrapped function as a pointer + size or range ,
How to make Swig correctly wrap the char * buffer that has been changed to C how is java something or the other?
And actually used the solutions as a guide to create an example.
This is my code in arrays.h file:
#include <iostream>
bool createArray(signed char ** arrCA, int * lCA){
*lCA = 10;
*arrCA = (signed char*) calloc(*lCA, sizeof(signed char));
for(int i = 0; i < *lCA; i++){
(*arrCA)[i] = i;
}
return *arrCA != NULL;
}
bool readArray(const signed char arrRA[], const int lRA){
for(int i = 0; i < lRA; i++){
std::cout << ((unsigned int) arrRA[i]) << " ";
}
std::cout << std::endl;
return true;
}
bool modifyArrayValues(signed char arrMA[], const int lMA){
for(int i = 0; i < 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 < *lMALOut; i++){
(*arrMALOut)[i] = arrMALIn[i];
}
return true;
}
This is the .i file for swig (arrays.i):
%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=&temp;"
%typemap(in, numinputs=0) int * lCA (int l) "$1=&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) {
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=&temp;"
%typemap(in, numinputs=0) int * lMALOut (int l) "$1=&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"
And finally, the Java code to test it:
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 < arr.length; i++){
System.out.print(arr[i] + " ");
}
}
System.out.println();
}
}
The example works, but I'm not sure if this is the right way, I mean:
is there an easier way to achieve the same result?
This code has memory leaks (on the one hand, I think it is because I am making a calloc, but I am not freeing it, but on the other hand, I am passing it to SetByteArrayRegion, so possibly freeing it will result in an error) ?
Does SetByteArrayRegion copy values โโor just a link ?, for example, if instead of actually executing a calloc, what should I do if I get an array from a C ++ object by a link that will be destroyed when I exit the area?
Is the array returned by Java correctly freed when it is invalidated?
, ?, , .i , , , , , , , , .
carrays.i, Java ++ Swig?, , 1000 , Java Socket String, 1 JNI- . byte[] Java, , .
:
, , , , , , Google. , , :
class SomeLibrary {
bool export(const std::string & sName, std::string & toExport);
bool import(const std::string & sName, const std::string & toImport);
}
, Protobuf ++ std::string , , Java, , Swig: std::string () java- [].
, - Java a byte[] Protobuf ( Java- ) byte[] protobuf. SWIGTYPE_p_std_string String import y , % extend, :
%extend SomeLibrary{
bool export(const std::string & sName, char ** toExportData, int * toExportLength);
bool import(const std::string & sName, char * toImportData, int toImportLength);
}
typemaps.
, , Java SWIG, Java byte[].