在C函数中注册java函数作为回调 [英] registering java function as a callback in C function

查看:230
本文介绍了在C函数中注册java函数作为回调的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图通过使用SWIG 1.3在Java中实现一些C代码。现在我
必须重建一些现有的C到Java代码,并提供一个函数
指向Java函数的C方法。



C代码:
net.c:

  void register_message_handler(context_t * ctx,message_handler_t handler){
context-> msg_handler =(void(*)(void *,coap_queue_t *,void *))handler;
}

client.c:

  void message_handler(context_t * ctx,queue_t * node,void * data){
...
}

int main (int argc,char ** argv){
// setup ctx
register_message_handler(ctx,message_handler);
}

我在Java中已经有了:

  public static void message_handler(def.SWIGTYPE_p_context_t ctx,def.SWIGTYPE_p_queue_t node,String data){} 

,这应该像在
上面的C代码中一样注册为回调,现在是Java:

  net.register_message_handler(ctx,message_handler); 

我发现的是
http://www.swig.org/Doc1.3/SWIGDocumentation.html#SWIG_nn30 ,包括本章末尾的
未定义的参考:
现在,关于函数指针支持的最后一个注释尽管SWIG不允许回调函数以目标语言编写,但是
可以使用类型码和其他高级SWIG功能。
这将在后面的章节中描述。
这是指什么?



我也找到了一个C ++的解决方案,但是有一种方法来适应这个C吗?
Swig c ++ w / Java在多态回调函数中失去类型
morphic-callback-functions



感谢您的帮助。

解决方案

我记得在SWIG手册中也把这个参考划过头。



您可以执行以下操作,而无需具备以下特征:




  • 您需要一个机制将传入的C回调分派到Java。为此,您需要调用的对象的对象ID和处理程序的方法ID。


  • 您还需要一个类ID和构造函数方法ID用于任何你想传递给java回调作为参数。您还需要缓存全局引用。


  • 在回调的C部分,查找方法ID,构造参数并调用Java。 / p>


  • 回调所在的线程需要连接到Java VM(使用JNI函数AttachCurrentThread())。这是你从你的JNIEnv指针。这个指针只在您调用的线程的上下文中有效。AttachCurrentThread()from!这意味着如果你有多个线程的回调,你需要在线程本地存储中缓存JNIEnv *。


  • 从JNI函数返回后的值


  • 确保在回调到Java之后检查ExceptionOccurred()。


  • 我发现使用Eclipse和Visual Studio调试相对容易,如下所示:启动main Java程序,将Visual Studio Debugger附加到该进程。您可以在任一侧设置断点。



I am trying to implement some C code in Java by using SWIG 1.3. Now I have to rebuild some existing C into Java code and to provide a function pointer to a Java function to the C method.

The C code: net.c:

void register_message_handler( context_t *ctx, message_handler_t handler) {
context->msg_handler = (void (*)( void *, coap_queue_t *, void *)) handler;
}

client.c:

void message_handler(context_t  *ctx, queue_t *node, void *data) {
...
}

int main(int argc, char **argv) {
// setup ctx
register_message_handler( ctx, message_handler );
}

All I already have in Java is:

public static void message_handler(def.SWIGTYPE_p_context_t ctx, def.SWIGTYPE_p_queue_t node, String data ) {}

and this should be registered as callback in the same way as it is done in the above C code, now in Java:

net.register_message_handler(ctx, message_handler);

What I found was http://www.swig.org/Doc1.3/SWIGDocumentation.html#SWIG_nn30 including an undefined reference at the end of this chapter: "And now, a final note about function pointer support. Although SWIG does not normally allow callback functions to be written in the target language, this can be accomplished with the use of typemaps and other advanced SWIG features. This is described in a later chapter." Where does this refer to?

I also found a solution for C++, but is there a way to adapt this to C? Swig c++ w/ Java loses type on polymorphic callback functions morphic-callback-functions

Thanks for your help.

解决方案

I remember scratching my head over this reference in the SWIG manual too.

You can do this as follows without the esoteric features:

  • You need a mechanism to dispatch the incoming C callback into Java. For that you need the object ID of the object that you are calling into, and the method ID of your handler. In your C registration helper, create Global References for those and cache them for use by the callback.

  • You also need a class ID and constructor method ID for anything that you want to pass to the java callback as a parameter. You also want to cache Global References to those.

  • In the C part of the callback, look up your method IDs, construct arguments and call into Java.

  • The thread that the callback comes in on, needs to be attached to the Java VM (with the JNI function AttachCurrentThread()). This is where you get your JNIEnv pointer from. This pointer is only valid in the context of the thread that you invoked AttachCurrentThread() from! What this means is that if you have callbacks coming in on multiple threads, you need to cache the JNIEnv * in thread local storage.

  • Make sure you check return values after returning from JNI functions

  • Make sure to check ExceptionOccurred() after any and all calls back into Java. Not doing this really gets you in trouble in hard to debug ways.

  • I found this relatively easy to debug with Eclipse and Visual Studio as follows: Start main Java program from Eclipse, attach Visual Studio Debugger to that process. You can set breakpoints on either side.

这篇关于在C函数中注册java函数作为回调的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆