1

I have a C function that accepts a function pointer. This function may be called multiple times. The function pointer of each call will be recorded and may be used in the future. How do I pass a java function as a function pointer to this C function? Or other available methods.

I am trying to write a C function to call a Java function and then pass this function as a function pointer. However, this is not working because I may need to pass in multiple Java functions, and it's not feasible to write a separate C function for each one. I can't disrupt the previously passed functions, such as by modifying global variables, because they might be called in the future.

It is difficult to change the existing C function.

3
  • 1
    This question is similar to: Call function pointer from JNI. If you believe it’s different, please edit the question, make it clear how it’s different and/or how the answers on that question are not helpful for your problem.
    – dan1st
    Commented Aug 14 at 4:55
  • Use an enum for each java function. Pass in the enum through jni and then in the java code, switch on the enum and execute the function. That way you don't need to write a C interface for every function.
    – cup
    Commented Aug 14 at 8:17
  • 1
    It sounds like these function pointers all have the same function type, but do not accept a pointer to user data? An example would be helpful here. Commented Aug 14 at 12:35

3 Answers 3

0

I have a C function that accepts a function pointer. This function may be called multiple times. The function pointer of each call will be recorded and may be used in the future. How do I pass a java function as a function pointer to this C function?

You don't. Even if you could obtain a pointer to a (non-native) Java method, which you can't, it would not be a pointer to a C function.

You can, very easily, obtain a pointer to a Java native method that is accessible to you, because this is a C function. That may or may not be useful to you, however, because all such methods require a pointer to a valid JNI environment, in the context of which the native method will be invoked.

Or other available methods.

You can write a C wrapper function that calls a Java method via JNI, in the context of an embedded JRE, and use a pointer to that. If you're driving this from the C side then that's almost certainly what you should do.

You could also wrap the Java code in a Java-based API server, that you could call via socket or URL or even by sending serialized instructions through a pipe. But from what limited description you've provided, I'm inclined to think that for your purposes, the wrapper function approach would be superior to any of these.

0

In java you use interfaces to pass methods to functions, this meaning you pass an object (while it is hidden by the language implementation) not a simple pointer (of course, you pass a reference to the object, which is some kind of pointer, but the class created on the fly to hold the call specific information is expressely hidden by the compiler to make the interface readable) This allows you to pass a method reference without having to first build a class implementing the interface required, but that is only notation, something is happening behind the scenes which is no as simple as the C way.

The reason for this is that, for static methods, you only need to know the method pointer to the function, but for non static method, you need also to know the instance, so both references, are needed this time (the reference to the method to be called and the reference to the instance on which you want the method to be called) This makes Java compiler to encode differently the call to the static method than the call to the non-static one (despite they have the same interface) This allows you to pass also a lambda, that refers in its body to in-scope objects (that the compiler enforces to be final due to the chances that the method is not known when it is going to be called, so the values should be constants at the time of the pass, to conserve their values at the time of the call)

When you specify e.g. myObject::toString in a call to a function that requires a function without parameters to be passed as parameter, first Java prepares all things to allow a call to a function called toString that requires an instance of MyClass which is the class to which myObject belongs, so you actually pass two references, one for the instance myObject and the other to the method Object.toString() if it has not been overriden in some subclass between Object and MyClass. And the class created on the fly, to define the pointer must have space to store the two pointers. In a different way, if you want to call a static String blabla() method, you can do it (it has the same footprint as myObject::toString, but will not require the instance) so when you pass MyClass::blabla as parameter, the class created has no reference to designate the instance, as you are passing a static method. This is all handled in a static way at compilation, but you link your C function at runtime, when it is loaded, and it will not have the appropiate interface to run any function pointer you can provide. The interface to C functions is stated by JNI, but you cannot impose Java how it has to define its functions to call them from C. The simple nature of pointer to function of C doesn't have a counterpart in Java.

This feature is also present in C++, for what is called a field reference or a method reference, and enforces the same preparation as Java does.

Anyway, in JNI there must be also ways by which you can callback a Java function/method from C. You should follow those guidelines, so you allow Java to prepare the interface adequately on each call, so you receive a properly initialized object. What you need to know is that the object will be an instance of an interface (the one that must be implemented by the definition of the parameter type) and you should make a callback call to the interface method published by that interface. Cannot be simpler!!!! ;)

0

You can split this problem into two parts:

  1. A generic C function (or set thereof) that invokes a Java method, given a jobject argument. This is trivial "hello world stuff".
  2. Specializing the C function above to a very specific object.

For the second part you can use libffi to generate a specialized function pointer for every separate Java object+method you want to invoke.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.