I'm using SWIG 2.0.10 in Ubuntu to call C++ code in Java.
My C++ code is:
//ImgPro.h:
#include <vector>
typedef struct _bin
{
char* name;
float value;
} Bin;
typedef struct imgprops
{
std::vector<Bin> color;
int width;
int height;
char *print;
} ImageProperties;
class ImgPro
{
public:
ImgPro();
ImageProperties *processImage(char* imagePath);
};
The processImage function definition is:
ImageProperties* ImgPro::processImage(char *imagePath)
{
ImageProperties* imgProp = new ImageProperties();
imgProp->width = 200;
imgProp->height = 200;
char* fp = new char(5);
strcpy(fp, "abc!");
imgProp->print = fp;
Bin outputBin1;
char *name1 = new char(strlen("red")+1);
strcpy(name1, "red");
outputBin1.name = name1;
outputBin1.value = 0.125;
Bin outputBin2;
char *name2 = new char(strlen("blue")+1);
strcpy(name2, "blue");
outputBin2.name = name1;
outputBin2.value = 0.27;
vector<Bin> tempVec;
tempVec.push_back(outputBin1);
tempVec.push_back(outputBin2);
imgProp->color = tempVec;
return imgProp;
}
So, to generate the jni code using swig, i've used the following swig file (note: the vector.i file was created using this example ) :
%module CBIR
// to handle char** has String_Array in Java
%include <various.i>
%include "vector.i"
%{
#include "ImgPro.h"
%}
// to handle char** has String_Array in Java
%apply char **STRING_ARRAY { char ** };
// memory release
%extend imgprops {
~imgprops(){
if($self != NULL)
{
// releasing print element
if($self->print != NULL)
delete[] $self->print;
// releasing vector elements
for(uint x = 0; x < $self->color.size(); x++)
{
Bin currentBin = $self->color[x];
if(currentBin.name != NULL)
delete[] currentBin.name;
}
// releasing stuct Pointer
delete $self;
}
}
}
%include "ImgPro.h"
%template(BinVec) std::vector<Bin>;
And this generates in the swig_wrap file the next function:
SWIGINTERN void delete_imgprops(imgprops *self){
if(self != NULL)
{
// releasing print element
if(self->print != NULL)
delete[] self->print;
// releasing vector elements
for(uint x = 0; x < self->color.size(); x++)
{
Bin currentBin = self->color[x];
if(currentBin.name != NULL)
delete[] currentBin.name;
}
// releasing stuct Pointer
delete self;
}
}
which is called in the delete ImageProperties c++ function.
However, running the following code in Java never releases the memory (calling the function delete_imgprops) allocated in C++:
ImgPro imgObject = new ImgPro();
ImageProperties propObject = imgObject.processImage("imagem123-jpg");
int width = propObject.getWidth();
int height = propObject.getHeight();
String fingerPrint = propObject.getPrint();
propObject.delete();
imgObject.delete();
So, after analyzing the code flow, i found the reason why the memory isn't released. The ImageProperties.Java file generated by SWIG contains, among others, the delete function:
public synchronized void delete() {
if (swigCPtr != 0) {
if (swigCMemOwn) {
swigCMemOwn = false;
CBIRJNI.delete_ImageProperties(swigCPtr);
}
swigCPtr = 0;
}
}
The line "CBIRJNI.delete_ImageProperties(swigCPtr);" is never called because the var swigCMemOwn is always false.
I understand that because the Java side doesn't alloc memory so it also doesn't release it, so what can i do to ensure that java releases memory without any modification on java files generated by swig?
The solution that i found to release the memory is to comment the if(swigCMemOwn) test on delete() function, but i don't think that it's the best way of do it!
Thanks, Sérgio