Search code examples
javajna

JNA: How to pass a string as void* from Java to C


I have successfully received a void* from a C function into Java and cast it into the apropriate type depending on context, but now I have to do the whole thing the other way around, and I can't get it to work.

Specifically, the function I am trying to call demands a void*, behind which, in this case, hides a char*, behind which of course hides a char[]. The C-function doesn't manipulate the data, it just reads it.

So I've tried creating a Byte[] from a string and then passing a pointer to the first element of it, like so:

    //transform the string into a byte array
    byte[] byte_value = new_value.getBytes();
    //create a pointer to the first byte
    ByteByReference valueptr = new ByteByReference(byte_value[0]);
    //pass the pointer to the function that sets the value
    int result = lib.gp_widget_set_value(widget, valueptr.getPointer()); 

To my surprise, nothing crashes. To my dismay, the function doesn't seem to get the data at all. Can anybody see what I'm doing wrong?

The function gp_widget_set_value was generated by JNAerator based on libgphoto2. The generated function header including generated comment looks like this:

/**
 * Original signature : <code>int gp_widget_set_value(CameraWidget*, const void*)</code><br>
 * <i>native declaration : /usr/include/gphoto2/gphoto2-widget.h:840</i>
 */
int gp_widget_set_value(Gphoto2Library.CameraWidget widget, Pointer value);

The documentation of the actual C function from the Gphoto API docs:

int gp_widget_set_value ( CameraWidget * widget, const void * value )

Sets the value of the widget.

Parameters widget a CameraWidget value

Returns a gphoto2 error code.

Please pass (char*) for GP_WIDGET_MENU, GP_WIDGET_TEXT, GP_WIDGET_RADIO, (float) for GP_WIDGET_RANGE, (int) for GP_WIDGET_DATE, GP_WIDGET_TOGGLE, and (CameraWidgetCallback) for GP_WIDGET_BUTTON.

In case you are wondering, the last line refers to the widget type, and yes, I'm making very sure that that is correct.


Solution

  • You don't need anything complicated. JNA takes care of most common C idioms. JNAerator is giving you literally what's in the function declarations; it can't figure out the semantic difference between a C string, a char buffer, an array of char, or a pointer to a single char.

    int gp_widget_set_value(Gphoto2Library.CameraWidget widget, String value);
    

    Note that the memory passed to the native function in this case is temporary and will be disposed of when the function returns. If you need the memory to stick around (not a good idea), you'd need to use Memory and maintain a reference to it.