Passing pointers between C and Java through JNI
I used the following approach:
in your JNI code, create a struct that would hold references to objects you need. When you first create this struct, return its pointer to java as a long
. Then, from java you just call any method with this long
as a parameter, and in C cast it to a pointer to your struct.
The structure will be in the heap, so it will not be cleared between different JNI calls.
EDIT: I don't think you can use long ptr = (long)&address;
since address is a static variable. Use it the way Gunslinger47 suggested, i.e. create new instance of class or a struct (using new or malloc) and pass its pointer.
Passing pointers between C and Java through JNI
There are various handy integer types in C. The one you want is probably intptr_t or uintptr_t:
return (jlong)(intptr_t) ptr;
The difference?
- Casting from
intptr_t
tojlong
and back is guaranteed to work providedjlong
is big enough (which you're implicitly assuming it is anyway). - Casting from
uinttptr_t
tojlong
and back avoids a sign-extension, but is undefined behaviour if theuintptr_t
is too big to fit in ajlong
(but all "sane" architectures/compilers just use two's complement arithmetic)
Passing a pointer from JNI to Java using a long
In your example
struct myStruct_s mystruct;
is a local variable on the stack, and therefore not available after the function returns. Possubly that's just a cut-down of your code, but if not then use a malloc(sizeof(struct myStruct_s)) to get yourself a heap allocation.
That then raises the question of when you are going to free that allocation, watch out for memory leaks.
Why does the JNI C API use a pointer-to-pointer instead of straight pointers for JNIEnv?
JNIEnv
is not really a pointer to a pointer, but to a data structure containing other (private) thread-specific information. The JNINativeInterface*
is just the first field in the struct, and the rest aren't public. This allows for more flexibility in VM's implementation of JNI function tables.
Some links here for the benefit of those who might come across this:
Threads and JNI - here it explains:
The JNI interface pointer (JNIEnv *) is only valid in the current thread. You must not pass the interface pointer from one thread to another, or cache an interface pointer and use it in multiple threads. The Java Virtual Machine will pass you the same interface pointer in consecutive invocations of a native method from the same thread, but different threads pass different interface pointers to native methods.
JNI spec
How to pass a C++ function pointer into a library's JNI functions
You need another layer of indirection. Since there's no such things as a function pointer in Java, you can't pass one to JNI. Instead, you have to pass it a Java object. Make an interface
public interface Callback {
void onAudioRecorded(int data[]);
}
Pass an instance of that to JNI. Then in JNI, write a function that calls the onAudioRecorded method of that Java object, and pass it to the function that needs a callback. remember that you need to hold an instance of that object at the JNI layer, and free it when you're finally done with it.
Related Topics
How to Bind an Object List with Thymeleaf
Sessions in Struts2 Application
How to Stop Selenium from Creating Temporary Firefox Profiles Using Web Driver
Programmatically Shut Down Spring Boot Application
Iterating Through a List in Reverse Order in Java
Transform Java Future into a Completablefuture
How to Add Shapes on Javafx Linechart
How to Iterate Through Range of Dates in Java
How to Make Line Animation Smoother
How to Check for a Valid Url in Java
What's the Default Value of Char
Output an Image File from a Servlet
Split Regex to Extract Strings of Contiguous Characters
Difference Between List and Array
How to Create a Class Literal of a Known Type: Class<List<String>>
How to Encrypt or Decrypt with Rijndael and a Block-Size of 256 Bits
Cors Allowed-Origin Restrictions Aren't Causing the Server to Reject Requests