I'm trying to map a Structure with contains some char *
fields using JNA. I get the following exception :
Exception in thread "main" java.lang.Error: Invalid memory access
Here is my C code :
The signature of the function called
extern "C" MATHLIBRARY_API ERR ErrorTest();
The C sample implementation I did as an example :
ERR sngErrorTest() {
ERR err;
char message[] = "My message";
char filename[] = "My file Name";
err.errorCode = OK;
err.errorDetails.fileName = NULL;
err.errorDetails.lineNumber = 1;
err.errorDetails.message = message;
err.errorDetails.fileName = filename;
return err;
}
The C types definition :
typedef enum {
OK = 0,
ERR_ONE,
ERR_TWO,
ERR_THREE,
ERR_FOUR,
ERR_FIVE,
ERR_SIX,
} ERR_CODE;
typedef struct {
char *fileName;
char *message;
int lineNumber;
} ERR_DETAILS;
typedef struct {
ERR_CODE errorCode;
ERR_DETAILS errorDetails;
} ERR;
Here is my java code :
public interface IFunctions extends Library {
public static class ERR_DETAILS extends Structure {
public static class ByValue extends ERR_DETAILS implements Structure.ByValue {}
public static class ByReference extends ERR_DETAILS implements Structure.ByReference {}
public Pointer fileName;
public Pointer message;
public int lineNumber;
@Override
protected List<String> getFieldOrder() {
return Arrays.asList(new String[] { "fileName", "message","lineNumber"});
}
}
public static class ERR_CODE {
public static int OK = 0;
public static int ERR_ONE = 1;
public static int ERR_TWO = 2;
public static int ERR_THREE = 3;
public static int ERR_FOUR = 4;
public static int ERR_FIVE = 5;
public static int ERR_SIX = 6;
}
public static class ERR extends Structure {
public static class ByValue extends ERR implements Structure.ByValue {}
public static class ByReference extends ERR implements Structure.ByReference {}
public ERR_CODE errorCode;
public ERR_DETAILS errorDetails;
@Override
protected List<String> getFieldOrder() {
return Arrays.asList(new String[] { "errorCode", "errorDetails"});
}
}
public ERR ErrorTest();
}
Here is my java test main class :
ERR err = IFunctions.ErrorTest();
err.errorDetails.fileName.getString(0);
?Thus I'm trying to isolate each type of the structure and I created as a sample the following C function :
signature :
extern "C" MATHLIBRARY_API ERR_CODE ErrorCode();
C implementation :
ERR_CODE ErrorCode() {
ERR_CODE err_code;
err_code = OK;
return err_code;
}
Java declaration
public interface IFunctions extends Library {
....
public ERR_CODE ErrorCode();
....
}
Call of my jna function :
ERR_CODE errCode = IFunctions.ErrorCode();
In that case I get the following error : Exception in thread "main" java.lang.IllegalArgumentException: Unsupported return type class ERR_CODE in function ErrorCode
Did I forget somethink regarding the enum type definition?
Finally I get the response to my issue.
In my JNA wrapper I had to explicitly defined that my function returns a structure by Value and not a structure By reference as it is done by default by JNA. As described in JNA API regarding Structure class : "When used as a function parameter or return value, this class corresponds to struct*. When used as a field within another Structure, it corresponds to struct. The tagging interfaces Structure.ByReference and Structure.ByValue may be used to alter the default behavior."
Thus the solution is as follow :
public interface IFunctions extends Library {
...
public ERR.ByValue ErrorTest();
}
Nothing else to change. Thanx for your help.