我们在其中一个库中有一个C函数,它在java中加载,它接受一个函数指针
功能定义如下
typedef char int8
typedef unsigned short uint16
uint32 poll_broadcasts(void *(pfn)(int8*,uint16));
在C中,使用如下
void handle_broadcasts( int8 *broadcast, uint16 length )
uint32 a = poll_broadcasts( (void*(*)(int8*,uint16)) handle_broadcasts )
但是当你使用Swig生成JNI包装器时,它会为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));
}
根据答案 How should I write the .i file to wrap callbacks in Java or C#
尝试在下面
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接口文件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接口BrodcastCallback.java
public interface BroadcastCallback {
//public void handle(String broadcast);
public void handle(char[] broadcast);
}
实施界面
class BtCallback implements BroadcastCallback {
@Override
public void handle(char[] broadcast) {
LOG.debug("Broadcast callback handled: " + broadcast.length);
}
}
最后使用时
BroadcastCallback cb = new BtCallback();
Test.set_handle_broadcast(cb, null);
Test.poll_broadcasts(Test.getHandle_broadcast());
没有编译错误,但是当程序运行并且poll_broadcasts调用从java传递的句柄广播函数指针(在C中)时,它会与EXCEPTION_ACCESS_VIOLATION崩溃。
看起来它必须对函数的int8 * arg做一些事情,但无法弄清楚
有人请帮忙。