JNA:如何将字符串作为void *从Java传递给C

时间:2015-12-08 15:23:17

标签: java jna

我已成功从C函数接收一个void *到Java中并根据上下文将其转换为适当的类型,但现在我必须以相反的方式完成整个事情,而我无法让它发挥作用。

具体来说,我试图调用的函数需要一个void *,在这种情况下,隐藏一个char *,后面当然隐藏了一个char []。 C函数不会操纵数据,它只是读取它。

所以我尝试从字符串创建一个Byte [],然后将指针传递给它的第一个元素,如下所示:

    //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()); 

令我惊讶的是,没有任何事情发生。令我沮丧的是,该功能似乎根本无法获取数据。谁能看到我做错了什么?

函数gp_widget_set_value由JNAerator基于libgphoto2生成。生成的函数头包括生成的注释如下所示:

/**
 * 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);

Gphoto API文档中实际C函数的文档:

  

int gp_widget_set_value(CameraWidget * widget,const void *     价值)

     

设置小部件的值。

     

参数       widget一个CameraWidget       价值

     

返回       gphoto2错误代码。

     

请传递(char *)GP_WIDGET_MENU,GP_WIDGET_TEXT,   GP_WIDGET_RADIO,(float)表示GP_WIDGET_RANGE,(int)表示   GP_WIDGET_DATE,GP_WIDGET_TOGGLE和(CameraWidgetCallback)   GP_WIDGET_BUTTON。

如果您想知道,最后一行是指小部件类型,是的,我确定这是正确的。

2 个答案:

答案 0 :(得分:1)

您可以使用以下命令以正确的编码获取字节:

byte[] bytes = new_value.getBytes( StandardCharsets.UTF_8 ); //or .US_ASCII

但您最需要做的是使用JNA's byte[] Native.toByteArray(String s)

如果出于某种原因无效,那么应该这样做:

Pointer m = new Memory( new_value.length() + 1 ); //assumes ASCII
m.setString( 0, new_value );
int result = lib.gp_widget_set_value( widget, m );

答案 1 :(得分:1)

你不需要任何复杂的事情。 JNA负责处理最常见的C语言。 JNAerator在字面上给出了函数声明中的内容;它无法弄清楚C字符串,char缓冲区,char数组或指向单个char的指针之间的语义差异。

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

请注意,在这种情况下传递给本机函数的内存是临时的,并且在函数返回时将被处理掉。如果你需要记忆(不是一个好主意),你需要使用Memory并保持对它的引用。