我正在尝试使用SWIG 1.3在Java中实现一些C代码。现在我 必须将一些现有的C重建为Java代码并提供一个功能 指向C方法的Java函数的指针。
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 loses type on polymorphic callback functions 的Morphic回调函数
感谢您的帮助。
答案 0 :(得分:10)
我还记得在SWIG手册中对此引用的讨论。
您可以按照以下方式执行此操作,而不需要深奥的功能:
您需要一种机制将传入的C回调分派到Java中。为此,您需要要调用的对象的对象ID以及处理程序的方法ID。在您的C注册助手中,为这些创建全局引用并缓存它们以供回调使用。
对于要作为参数传递给java回调的任何内容,还需要类ID和构造函数方法ID。您还想将全局引用缓存到那些。
在回调的C部分,查找方法ID,构造参数并调用Java。
回调所在的线程需要附加到Java VM(使用JNI函数AttachCurrentThread())。这是从中获取JNIEnv指针的地方。此指针仅在您调用AttachCurrentThread()的线程的上下文中有效!这意味着如果你有多个线程上的回调,你需要在线程本地存储中缓存JNIEnv *。
确保从JNI函数返回后检查返回值
确保在任何和所有回调到Java之后检查ExceptionOccurred()。不这样做真的让你在难以调试方面遇到麻烦。
我发现使用Eclipse和Visual Studio调试相对容易,如下所示:从Eclipse启动主Java程序,将Visual Studio Debugger附加到该进程。您可以在任何一方设置断点。