Pass Socket data to JNA Function with Void* Parameter

540 views Asked by At

On Windows, I have some 3rd party TCP data coming in through a Java Socket, and I'm trying to figure out how to pass the data into a C Library provided by the same 3rd party - using JNA. I am new to all things JNA/JNI/C etc.

The 3rd Party library will take incoming bytes from the socket and decode them to the right message type. Since the data coming in is of arbitrary length, has no end delimiter, and the start delimiter is very short (so could appear in the middle of the data and not be an actual delimiter) it's actually probably easier to figure out how to use this library though JNA instead of roll my own (or learn C).

I've managed to use jnaerator to generate source code from the C header files. I've also successfully called a simple C function requiring no parameters. However, when trying to use a function that requires passing "raw data" to a C function that originally accepted a void pointer, I'm not sure how to proceed.

Here are relevant snippets from the code.

//CExportTypes.h
typedef unsigned int XUint;
//also defines structs: XMessageType, XCrypto, XAlarm, etc.

//CLibrary.h
XStatus XGetMessageType(void* bytesRecv, XUint numBytes, XMessageType* type, XUint* serial, XUint* msgLen);
XStatus XDecodeAlarm(void* bytesRecv, XUint numBytes, XCrypto* key, XAlarm* decodedAlarm);

//CLibrary.java (Generated)
int XGetMessageType(Pointer bytesRecv, int numBytes, IntBuffer type, IntBuffer serial, IntBuffer msgLen);
int XDecodeAlarm(Pointer bytesRecv, int numBytes, XCrypto key, XAlarm decodedAlarm);

How do I get the incoming

int = Socket.getInputStream()

"raw data" into a Pointer that the JNA function expects? What other gotchas do I need to be aware of? Endianness, unsigned byte issues, etc?

I know that may not be much to go on, but I appreciate any help I can get.

1

There are 1 answers

0
Samuel Audet On

Use a SocketChannel to read into a direct NIO buffer, which we can dereference from JNI. Something like:

SocketChannel client = SocketChannel.open(address);
ByteBuffer buffer = ByteBuffer.allocate(42);
client.read(buffer);

And call your functions with Buffer as parameter instead of Pointer.