简体   繁体   English

映射 c++ function 与 JNA

[英]Mapping c++ function with JNA

I have a problem trying to map this c++ function with JNA.我在使用 JNA 尝试 map 这个 c++ function 时遇到问题。

https://www.inventcom.net/fanuc-focas-library/program/cnc_rdexecprog https://www.inventcom.net/fanuc-focas-library/program/cnc_rdexecprog

FWLIBAPI short WINAPI cnc_rdexecprog(unsigned short FlibHndl, unsigned short *length, short *blknum, char *data);

I tried with these mappings in java but dont work:我在 java 中尝试了这些映射,但不起作用:

short cnc_rdexecprog(short FlibHndl, ShortByReference length, ShortByReference blknum, String data);
short cnc_rdexecprog(short FlibHndl, ShortByReference length, ShortByReference blknum, Pointer data);
short cnc_rdexecprog(short FlibHndl, ShortByReference length, ShortByReference blknum, Memory data);

The first mapping works but return me the same String that I send, the second and third shows this error:第一个映射有效,但返回我发送的相同字符串,第二个和第三个显示此错误:

Exception in thread "AWT-EventQueue-0" java.lang.Error: Invalid memory access

I was able to get similar functions working thanks to this thread: Use C++ DLL from Java with JNA由于这个线程,我能够获得类似的功能: Use C++ DLL from Java with JNA

I think that the problem are in the output parameter "char *data".我认为问题出在 output 参数“char *data”中。 How to map this function? map 这个 function 如何?

The char * type is expecting a buffer of bytes (characters in C). char *类型需要一个字节缓冲区(C 中的字符)。

Java's String type is immutable ( const char * ) so the native code can't modify it, as you've observed.正如您所观察到的,Java 的String类型是不可变的( const char * ),因此本机代码无法修改它。 The Pointer type would work but as you see from the error message, doesn't point to allocated memory. Pointer类型可以工作,但正如您从错误消息中看到的那样,它并不指向已分配的 memory。 Memory also works (and extends Pointer ) but requires you to actually allocate the memory with your parameter. Memory也可以工作(并扩展Pointer ),但需要您使用参数实际分配 memory 。 For example:例如:

Memory buffer = new Memory(bufferSize);

You could pass buffer as either a Pointer or Memory to your method and it would work.您可以将buffer作为PointerMemory给您的方法,它会起作用。

The problem here is determining what the value of bufferSize should be.这里的问题是确定bufferSize的值应该是什么。 This is where the API helpfully tells you:这是API 有用地告诉您的地方:

length [ in/out ] Specify the address of the variable which shows the number of characters to be read. length [ in/out ] 指定显示要读取的字符数的变量的地址。 Set the number of characters to be read to this variable *length(length).将要读取的字符数设置为此变量 *length(length)。 After reading, the number of characters actually read is set in this variable *length(length) again.读取后,实际读取的字符数再次设置在这个变量*length(length)中。

You need to coordinate the size of your buffer and the length you pass in the second argument.您需要协调缓冲区的大小和传入第二个参数的长度。 Consult the documentation to see if there is any constant defining the max length of the string you expect, and use that.请查阅文档以查看是否有任何常量定义了您期望的字符串的最大长度,并使用它。 (Based on this example , it may be MAX_PROG_SIZE (1024*2), with an extra byte added for the null terminator. But you should verify this yourself.) (基于此示例,它可能是MAX_PROG_SIZE (1024*2),并为 null 终结器添加了一个额外的字节。但您应该自己验证这一点。)

If that doesn't exist, a standard JNA idiom is:如果不存在,标准的 JNA 习惯用法是:

  • Declare a size and pass it to the native function (length and allocated buffer should match)声明一个大小并将其传递给本机 function(长度和分配的缓冲区应该匹配)
  • Check for a result code indicating you didn't provide enough characters (probably EW_LENGTH (2))检查结果代码是否表明您没有提供足够的字符(可能是EW_LENGTH (2))
  • Repeat with a larger buffer until the string fits.用更大的缓冲区重复,直到字符串适合。

Alternately you can start with a much larger value.或者,您可以从更大的值开始。

In all cases, remember to add 1 to the actual max string length to account for the null terminator.在所有情况下,请记住将实际最大字符串长度加 1 以说明 null 终止符。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM