m0_69707535 2023-11-13 12:10 采纳率: 62.5%
浏览 13
已结题

java调用C++接口回调如何实现

//设置数据回调方法
    public native int setDataCB(Cb cb);
    //
    public interface Cb extends Callback{
        void myCb(int int32, byte b);
    } 


setDataCB(void (*cb)(uint32,void8))
{
  dataCB= std::bind_front(cb);
}
/*Java生成头文件
 * Class:     DevSDK_jni_DevSDK
 * Method:    setDataCB
 * Signature: (LDevSDK/jni/DevSDK/Cb;)I
 */
JNIEXPORT jint JNICALL Java_DevSDK_jni_DevSDK_setDataCB
  (JNIEnv *, jobject, jobject);
{

//如何实现?????

}
java
  • 写回答

3条回答 默认 最新

  • K_n_i_g_h_t_1990 2023-11-13 14:25
    关注
    • Java调用C++接口回调的一种方法是使用JNI(Java Native Interface)技术,即Java本地接口,它可以让Java代码和本地代码(如C++)进行交互,实现互相调用¹² 。

    • JNI的基本原理是,Java代码通过声明native方法,来表示需要调用本地代码的方法,然后通过javah工具生成对应的本地头文件,再在本地代码中实现这些方法,并编译成动态链接库(如dll或so文件),最后在Java代码中加载这些动态链接库,就可以调用本地方法了 。

    • JNI中,如果要实现本地代码调用Java代码的回调,需要传递一个Java对象作为参数,然后在本地代码中获取这个对象的类、方法、字段等信息,再通过反射机制来调用这些信息,从而实现回调¹。

    • 以你的代码为例,你可以参考以下的步骤来实现Java调用C++接口回调:

      • 在Java代码中,定义一个接口Cb,用来表示回调函数的抽象,然后定义一个native方法setDataCB,用来传递一个Cb对象给本地代码,如下:
      //设置数据回调方法
      public native int setDataCB(Cb cb);
      //
      public interface Cb extends Callback{
          void myCb(int int32, byte b);
      }
      
      • 在C++代码中,定义一个全局变量dataCB,用来存储回调函数的指针,然后定义一个函数setDataCB,用来接收一个Cb对象,并将其转换为回调函数的指针,如下:
      //定义一个全局变量,用来存储回调函数的指针
      void (*dataCB)(uint32,void8);
      
      //定义一个函数,用来接收一个Cb对象,并将其转换为回调函数的指针
      setDataCB(void (*cb)(uint32,void8))
      {
          dataCB= std::bind_front(cb);
      }
      
      • 在Java代码中,使用javah工具生成本地头文件,如下:
      javah DevSDK.jni.DevSDK
      
      • 在本地头文件中,实现setDataCB函数,用来接收一个JNIEnv指针、一个jobject对象和一个jobject对象,然后通过JNIEnv指针获取Cb对象的类和方法信息,再通过GetMethodID和FromReflectedMethod函数将其转换为回调函数的指针,如下:
      /*Java生成头文件
      * Class:     DevSDK_jni_DevSDK
      * Method:    setDataCB
      * Signature: (LDevSDK/jni/DevSDK/Cb;)I
      */
      JNIEXPORT jint JNICALL Java_DevSDK_jni_DevSDK_setDataCB
      (JNIEnv * env, jobject obj, jobject cb)
      {
          //获取Cb对象的类信息
          jclass cbClass = env->GetObjectClass(cb);
          //获取Cb对象的方法信息
          jmethodID cbMethod = env->GetMethodID(cbClass, "myCb", "(IB)V");
          //将Cb对象的方法信息转换为回调函数的指针
          dataCB = (void (*)(uint32, void8))env->FromReflectedMethod(cbMethod);
          return 0;
      }
      
      • 在C++代码中,定义一个函数process,用来执行回调函数,如下:
      //定义一个函数,用来执行回调函数
      process(uint32 int32, void8 b)
      {
          //调用回调函数
          dataCB(int32, b);
      }
      
      • 在Java代码中,加载本地动态链接库,并调用setDataCB和process方法,如下:
      //加载本地动态链接库
      static {
          System.loadLibrary("DevSDK");
      }
      
      //调用setDataCB方法,传递一个Cb对象
      setDataCB(new Cb() {
          @Override
          public void myCb(int int32, byte b) {
              //在回调函数中处理响应
              System.out.println("int32 = " + int32 + ", b = " + b);
          }
      });
      
      //调用process方法,传递一些参数
      process(100, 1);
      
      • 运行Java代码,可以看到回调函数被执行,输出如下:
      int32 = 100, b = 1
      
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论 编辑记录
查看更多回答(2条)

报告相同问题?

问题事件

  • 系统已结题 12月1日
  • 已采纳回答 11月23日
  • 创建了问题 11月13日

悬赏问题

  • ¥50 远程桌面打开Mastercam、没有许可证、物理机打开正常
  • ¥15 ubuntu安装gdal后java读取tif文件报错
  • ¥15 请问lammps怎么做两种金属连接的原子浓度分布图
  • ¥15 求jacquard数据集
  • ¥15 w10部分软件不能联网
  • ¥15 关于安装hbase的问题(操作系统-windows)
  • ¥15 novnc连接pve虚拟机报错安全协议不支持262
  • ¥15 设备精度0.03给多少公差能达到CPK1.33
  • ¥15 qt+ffmpeg报错non-existing PPS 0 referenced
  • ¥50 MacOS 使用虚拟机安装k8s