Transfering callback function to jni

J

John Smith

Hi everyone,

Lets say you have a jni function which accepts a callback function.
This function should be set from within java and called if a failure happens
in the jni code.

The only examples I've seen of java callbacks are where the java function is
already known and hardcoded in the jni code. However assume you have a java
class which calls this jni function you want to be able to create multiple
objects of this class pointing to each their different function.

In other words how can I make a java function into a jni function pointer
and transfer it to the jni code. In .NET this is quite easy by using
delegates.

Is it possible in java too or do you need to hardcode the function name
inside jni?

Thanks in advance.

-- John
 
J

jan V

In other words how can I make a java function into a jni function pointer
and transfer it to the jni code. In .NET this is quite easy by using
delegates.

Is it possible in java too or do you need to hardcode the function name
inside jni?

If you take a few steps back, maybe you'll agree that you're trying to solve
a messy architectural problem. Instead of finding a solution for your stated
problem, maybe you should re-architect the Java-JNI-C interface so that
you/it obey the KISS principle. E.g. break the C code into more primitive
chunks which are not given the responsibility to call Java when an error
occurs, but simply include a C routine which tells you whether an error
occurred or not.

But before you consider this route, are you 500% sure you need JNI at all?
 
J

John Smith

If you take a few steps back, maybe you'll agree that you're trying to
solve
a messy architectural problem. Instead of finding a solution for your stated
problem, maybe you should re-architect the Java-JNI-C interface so that
you/it obey the KISS principle. E.g. break the C code into more primitive
chunks which are not given the responsibility to call Java when an error
occurs, but simply include a C routine which tells you whether an error
occurred or not.

But before you consider this route, are you 500% sure you need JNI at all?
Yes I am sure I need JNI.
Thing is that I have a library already written in C and I want to expose
this library through a java wrapper. Building functions which signals errors
is one way to solve it but it's not very efficient though. The calling java
application needs to poll for the error to happen.
I don't like the idea of methods which are hardcoded into jni as callbacks.
This is just messy if you have more java objects of the wrapper class and
forces it to become a singleton class.

I understand that looking from a strict java perspective it's not very
efficient. However in my case it's a matter of java support to my
application or none at all. Rewriting thousands of lines from C++ into java
is not an option.

Thanks in advance.

-- John
 
C

Chris Uppal

John said:
Is it possible in java too or do you need to hardcode the function name
inside jni?

You either have to hard-code the function name in the JNI code, or tell the JNI
code somehow what the name of the function is. Overall the former is simpler
;-)

If it bothers you, you can set up a helper class like:

abstract class Callback
{
abstract void doIt();
}

And then pass instances of nested and/or inner classes to JNI, e.g:

class Example
{
private void
theRealHandler(String location)
{
// just for example
System.err.println("Error in Example." + location + "()");
}

void
methodThatUsesJNI()
{
Callback callback = new Callback()
{
void doIt()
{

theRealHander("methodThatUsesJNI");
}
};
callJNI(params, callback);
}
}

If you see what I mean (and if I haven't cocked up the bloody obfuscatory
anonymous class syntax again).

The idea is that you define the Callback class once, and use "local" subclasses
of it everywhere. JNI only needs to know about (and hard-code) the one
Callback method.

-- chris
 
A

A_Wieminer

Is it possible in java too or do you need to hardcode the function name
You either have to hard-code the function name in the JNI code, or tell the JNI
code somehow what the name of the function is. Overall the former is simpler
;-)

If it bothers you, you can set up a helper class like:

abstract class Callback
{
abstract void doIt();
}

And then pass instances of nested and/or inner classes to JNI, e.g:

class Example
{
private void
theRealHandler(String location)
{
// just for example
System.err.println("Error in Example." + location + "()");
}

void
methodThatUsesJNI()
{
Callback callback = new Callback()
{
void doIt()
{

theRealHander("methodThatUsesJNI");
}
};
callJNI(params, callback);
}
}

If you see what I mean (and if I haven't cocked up the bloody obfuscatory
anonymous class syntax again).

The idea is that you define the Callback class once, and use "local" subclasses
of it everywhere. JNI only needs to know about (and hard-code) the one
Callback method.

Nice and simple abstract callback layer. However, I have always wondered
whether its safe to call java method from _any_ native thread. Virtual
machine does not bother the origin thread it is just us to maintain a
thread safety code when doing callbacks from native side?
 
C

Chris Uppal

A_Wieminer said:
However, I have always wondered
whether its safe to call java method from _any_ native thread. Virtual
machine does not bother the origin thread it is just us to maintain a
thread safety code when doing callbacks from native side?

I'm not sure that I have understood your question properly. If the following
doesn't answer your question then please ask again.

There are two parts to this.

The first part is that there are definite rules about which threads are allowed
to call back from native code into Java. If thread is executing native code
because that code has been called from Java, then it's OK for it to call back
into Java (on the same thread). If a thread is the one that originally created
the JVM, then it can call into Java whenever it wants. Otherwise, as I
understand it (I've never had to use this so I may be wrong), a thread can only
call Java code if it has registered itself with the JVM by using the JNI
AttachCurrentThread() function (or similar). Basically you can only call Java
code from native threads that the JVM "knows" about. A related problem for JNI
programmers, is that the references to Java objects that Java provides when it
invokes JNI code, are only valid on that thread. If the programmer wants to
store a reference to the object for use on another thread, then s/he has to
convert the reference to a so-called "global" reference (and remember to
release it later). So, for instance, the Callback object in my example
couldn't just be stored or passed from thread to thread in the OP's JNI code --
if he wanted to do that, then he'd have to code for it specially, following the
JNI rules.

The second part is that -- providing the above rules are followed -- the
callback can be invoked from any thread. In this case the picture is just the
same as if the callback had been invoked from Java code running in a different
(or potentially different) Java Thread. If that possibility is allowed by your
application design (it may not be), then you have to code for it by using
synchronized methods and blocks in the usual way. (It is also possible to
acquire/release the locks associated with any object directly from JNI, but I'd
think that would usually be a very bad idea -- and a lot of extra effort too.)

-- chris
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,012
Latest member
RoxanneDzm

Latest Threads

Top