JNI for C using Swig & trouble with function pointer callback

匿名 (未验证) 提交于 2019-12-03 00:56:02

问题:

we have a C function in one of the libraries which are loaded in java, which accepts a function pointer

function defination as below

typedef char int8 typedef unsigned short uint16  uint32 poll_broadcasts(void *(pfn)(int8*,uint16)); 

In C it is used as below

void handle_broadcasts( int8 *broadcast, uint16 length )  uint32 a = poll_broadcasts( (void*(*)(int8*,uint16)) handle_broadcasts ) 

But when you use Swig to generate JNI wrapper it creates following definition for poll_broadcast

public static long poll_broadcasts(SWIGTYPE_p_f_p_char_unsigned_short__p_void pfn) {     return TestJNI.poll_broadcasts(SWIGTYPE_p_f_p_char_unsigned_short__p_void.getCPtr(pfn));   } 

As per answer for
How should I write the .i file to wrap callbacks in Java or C#

Tried below

test.h

void * data;  typedef void* (*callback_handle_broadcast_t)(int8*, uint16);  static callback_handle_broadcast_t handle_broadcast;  static void set_handle_broadcast(callback_handle_broadcast_t cb, void *userdata) {     handle_broadcast = cb;     data = userdata; } 

Swig interface file Test.i

%module Test  %include "cpointer.i" %include "carrays.i" %include "various.i" %include "arrays_java.i"  %pointer_functions(int, intp); %pointer_functions(char, charp);  %include "arrays_java.i" %include "typemaps.i"  %{  #include <assert.h>  #include "test.h"  struct callback_data {   JNIEnv *env;   jobject obj; };    void java_callback(int8* arg1, uint16 arg2, void *ptr) {   struct callback_data *data = ptr;   const jclass callbackInterfaceClass = (*data->env)->FindClass(data->env, "BroadcastCallback");   assert(callbackInterfaceClass);   const jmethodID meth = (*data->env)->GetMethodID(data->env, callbackInterfaceClass, "handle", "([C)V");   assert(meth);    jcharArray charArr = (*data->env)->NewCharArray(data->env, arg2);   (*data->env)->CallVoidMethod(data->env, data->obj, meth, (jcharArray)charArr);  }   %}  %typemap(jstype) callback_handle_broadcast_t cb "BroadcastCallback"; %typemap(jtype) callback_handle_broadcast_t cb "BroadcastCallback"; %typemap(jni) callback_handle_broadcast_t cb "jobject"; %typemap(javain) callback_handle_broadcast_t cb "$javainput";   %typemap(in,numinputs=1) (callback_handle_broadcast_t cb, void *userdata) {   struct callback_data *data = malloc(sizeof *data);   data->env = jenv;   data->obj = JCALL1(NewGlobalRef, jenv, $input);   JCALL1(DeleteLocalRef, jenv, $input);   $1 = java_callback;   $2 = data; }   %include "test.h" 

Java Interface BrodcastCallback.java

public interface BroadcastCallback {     //public void handle(String broadcast);     public void handle(char[] broadcast); } 

Implement the interface

class BtCallback implements BroadcastCallback {      @Override     public void handle(char[] broadcast) {         LOG.debug("Broadcast callback handled: " + broadcast.length);     } } 

Finally when used

BroadcastCallback cb = new BtCallback(); Test.set_handle_broadcast(cb, null); Test.poll_broadcasts(Test.getHandle_broadcast()); 

There is no compilation error, but when program is run and and poll_broadcasts calls the handle broadcast function pointer (within C) passed from java, it crashes with EXCEPTION_ACCESS_VIOLATION.

Looks like it has to do something with int8* arg of the function, but can't figure out

somebody please help.

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!