栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

我应该如何编写.i文件以用Java或C#包装回调

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

我应该如何编写.i文件以用Java或C#包装回调

如果您有机会通过回调传递一些数据,则可以执行此操作,但是您需要编写一些JNI胶。我整理了一个完整的示例,说明如何将C样式的回调映射到Java接口。

您需要做的第一件事是确定在Java方面合适的接口。我假设在C中我们有如下回调:

typedef void (*callback_t)(int arg, void *userdata);

我决定用Java将其表示为:

public interface Callback {  public void handle(int value);}

void *userdata
因为我们可以将状态存储在琐碎
Object
实现的Java中,所以Java方面的损失不是真正的问题
Callback
)。

然后,我编写了以下头文件(它实际上不应该只是头文件,但它使事情变得简单)来进行包装:

typedef void (*callback_t)(int arg, void *data);static void *data = NULL;static callback_t active = NULL;static void set(callback_t cb, void *userdata) {  active = cb;  data = userdata;}static void dispatch(int val) {  active(val, data);}

我能够使用以下接口成功包装此C:

%module test%{#include <assert.h>#include "test.h"// 1:struct callback_data {  JNIEnv *env;  jobject obj;};// 2:void java_callback(int arg, void *ptr) {  struct callback_data *data = ptr;  const jclass callbackInterfaceClass = (*data->env)->FindClass(data->env, "Callback");  assert(callbackInterfaceClass);  const jmethodID meth = (*data->env)->GetMethodID(data->env, callbackInterfaceClass, "handle", "(I)V");  assert(meth);  (*data->env)->CallVoidMethod(data->env, data->obj, meth, (jint)arg);}%}// 3:%typemap(jstype) callback_t cb "Callback";%typemap(jtype) callback_t cb "Callback";%typemap(jni) callback_t cb "jobject";%typemap(javain) callback_t cb "$javainput";// 4:%typemap(in,numinputs=1) (callback_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"

该接口包含很多部分:

  1. 一个
    struct
    存储要对Java接口的调用所需的信息。
  2. 的实现
    callback_t
    。它接受
    struct
    我们刚刚定义的用户数据,然后使用一些标准的JNI将调用调度到J​​ava接口。
  3. 某些类型映射会导致
    Callback
    对象作为real直接传递给C实现
    jobject
  4. 一个类型图,它
    void*
    在Java端隐藏,并设置
    callback
    数据并为实函数填充相应的参数,以使用我们刚刚编写的用于将调用分派回Java的函数。它采用对Java对象的全局引用,以防止随后对其进行垃圾回收。

我写了一个Java类来测试它:

public class run implements Callback {  public void handle(int val) {    System.out.println("Java callback - " + val);  }  public static void main(String argv[]) {    run r = new run();    System.loadLibrary("test");    test.set(r);    test.dispatch(666);      }}

如您所愿。

需要注意的几点:

  1. 如果您
    set
    多次调用,它将泄漏全局引用。您或者需要提供一种取消设置回调的方法,防止多次设置或使用弱引用。
  2. 如果您有多个线程,您将需要
    JNIEnv
    比这里的人更加聪明。
  3. 如果要混合使用Java和C的回调实现,则需要在此解决方案上进行大量扩展。您可以将C函数公开用作回调函数,
    %constant
    但是这些类型映射将阻止您的包装函数接受此类输入。可能您想提供重载来解决此问题。

我相信C#的解决方案会有些相似,不同的Typemap名称和用C编写的回调函数的不同实现。



转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/425801.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号