zoukankan      html  css  js  c++  java
  • C++回调函数调用Java接口抽象函数

    原文:http://www.diybl.com/course/3_program/c++/cppjs/20110103/552247.html

    项目中很多代码采用C++编写,配置界面则采用BS结构,使用Java语言进行设置。因此需要实现Java调用C++编写的函数库(dll文件或so文件),采用的技术为JNI(Java Native Interface),对于常用的调用方式在《The Java Native Interface Programmer's Guide and Specification》一书中有详细的描述,不在进行描述。本文中主要介绍在动态链接库中如果含有回调函数作为函数参数的C++函数如何使用JNI实现调用。在C++中函数定义格式为:

        typedef int (*UserProcess)(int nEncrptType);

        CALLBACK_API int Process(UserProcess cb,int nCompanID);

    即如何采用Java语言实现Process函数?下面将分别针对C++和Java语言使用回调函数进行说明。

    1.回调函数库

    本文中定义了一个简单的回调函数接口,目的是根据公司ID进行加密,加密函数为回调函数。头文件定义如下

    1. #ifdef CALLBACK_EXPORTS
    2. #define CALLBACK_API __declspec(dllexport)
    3. #else
    4. #define CALLBACK_API __declspec(dllimport)
    5. #endif

    6. #ifdef __cplusplus
    7. extern "C"
    8. {
    9. #endif
    10.     typedef int (*UserProcess)(int nEncrptType);
    11.     CALLBACK_API int Process(UserProcess cb,int nCompanID);
    12. #ifdef __cplusplus
    13. }
    14. #endif



    其实现文件为

    1. #include "stdafx.h"
    2. #include "CallBack.h"


    3. CALLBACK_API int Process(UserProcess cb,int nCompanID)
    4. {
    5.     if(cb == NULL)
    6.     {
    7.         return -1;
    8.     }

    9.     cb(nCompanID);
    10.     return 0;
    11. }


     
    2.C++语言使用回调函数库
    用法比较简单,直接实现一个满足UserProcess定义的函数,然后将其传递给Process函数即可,见下文代码内容。

    1. #include "stdafx.h"
    2. #include "../CallBack/CallBack.h"

    3. int WanporProcess(int i)
    4. {
    5.     printf("Process = %d ",i);
    6.     return i;
    7. }
    8. int _tmain(int argc, _TCHAR* argv[])
    9. {

    10.     Process(WanporProcess,100);
    11.     return 0;
    12. }

     
    加密函数将公司ID直接输出,未进行其他处理。
    3.Java语言使用回调函数
    这个过程相对于C++显得比较繁琐,主要包含以下一个过程:
    3.1编写回调函数的抽象接口,并实现一个回调类;
    3.2在JNI中安装回调接口类
    3.3实现C++的回调函数,在此回调函数中获取抽象接口类对象、回调函数的接口名称、调用回调函数
    3.4调用process进行回调函数执行
    2.5卸载回调类
    下面依次实现上述中的内容
    3.1回调函数接口定义
    1. package cn.com.wanpor;
    2. //编写回调函数接口


    3. public interface CBInterface{
    4.     public abstract int UserProcess(int encryptType);
    5. }


    3.2实现回调类

    1. //实现回调类


    2. class WanporCB implements CBInterface {
    3.     public int UserProcess(int encryptType){
    4.         System.out.println("Java = " + 3*encryptType);
    5.         return 0;
    6.     }
    7. }


    3.3C++ JNI代码中安装回调类

    1. #include "stdafx.h"
    2. #include "../CallBack/CallBack.h"
    3. #include "cn_com_wanpor_CallBackJNI.h"

    4. typedef struct CBData{
    5.     UserProcess m_pfnUserProcess;
    6.     jobject m_objInterface;
    7.     JNIEnv* m_pEnv;
    8.     jobject m_objCallBack;
    9. }CBData;

    10. CBData g_cbData;
    11. JNIEXPORT jint JNICALL Java_cn_com_wanpor_CallBackJNI_setUserCallBack
    12. (JNIEnv * env, jobject obj, jobject cb)
    13. {
    14.     
    15.     g_cbData.m_pEnv = env;
    16.     g_cbData.m_objCallBack = env->NewGlobalRef(obj);
    17.     g_cbData.m_objInterface = env->NewGlobalRef(cb);

    18.     return 0;
    19. }


    3.4实现C++回调函数

    1. int ProcessJNICB(int nEncrpytType)
    2. {
    3.     JavaVM* pVm;
    4.     g_cbData.m_pEnv->GetJavaVM(&pVm);
    5.     pVm->AttachCurrentThread((void**)&g_cbData.m_pEnv,NULL);

    6.     jclass jclsProcess = g_cbData.m_pEnv->GetObjectClass(g_cbData.m_objInterface);
    7.     if (jclsProcess == NULL)
    8.     {
    9.         printf("jclsProcess = NULL ");
    10.         return -1;
    11.     }
    12.     jmethodID jmidProcess = g_cbData.m_pEnv->GetMethodID(jclsProcess,"UserProcess","(I)I");
    13.     if (jmidProcess == NULL)
    14.     {
    15.         printf("jmidProcess = NULL ");
    16.         return -2;
    17.     }

    18.     g_cbData.m_pEnv->CallIntMethod(g_cbData.m_objInterface,jmidProcess,nEncrpytType);
    19.     
    20.     pVm->DetachCurrentThread();
    21.     
    22.     return 0;
    23. }


    3.5执行回调函数

    1. JNIEXPORT jint JNICALL Java_cn_com_wanpor_CallBackJNI_process
    2. (JNIEnv * env, jobject obj, jint nCompanyID)
    3. {
    4.     Process(ProcessJNICB,nCompanyID);
    5.     return 0;
    6. }

     
    3.6卸载回调类
    1. JNIEXPORT jint JNICALL Java_cn_com_wanpor_CallBackJNI_resetUserCallBack
    2. (JNIEnv * env, jobject objCallBack, jobject objInterface)
    3. {
    4.     g_cbData.m_pEnv->DeleteGlobalRef(objInterface);
    5.     g_cbData.m_pEnv->DeleteGlobalRef(objCallBack);
    6.     return 0;
    7. }


    4.Java测试程序
    下面的代码是对JNI接口的测试程序,WanporCB实现了回调接口,回调函数返回值为0,但打印出3*nCompany的值,程序执行函数的顺序是:
    创建回调函数接口实例
    创建测试对象
    安装回调类
    执行加密
    卸载回调类
    代码如下:

    1. package cn.com.wanpor;

    2. //实现回调类


    3. class WanporCB implements CBInterface {
    4.     public int UserProcess(int encryptType){
    5.         System.out.println("Java = " + 3*encryptType);
    6.         return 0;
    7.     }
    8. }
    9. public class CallBackJNI{
    10.     static{
    11.         System.load("E:\Program Files\Java\jdk1.5.0_15\bin\CallBackJNI.dll");
    12.     }
    13.     
    14.     //设置回调函数


    15.     public native int setUserCallBack(CBInterface cb);
    16.     //清除回调函数


    17.     public native int resetUserCallBack(CBInterface cb);
    18.     //执行用户自定义加密


    19.     public native int process(int companyID);
    20.     
    21.     //测试程序


    22.     public static void main(String[] argv){
    23.         CallBackJNI cbj = new CallBackJNI();
    24.         WanporCB wcb = new WanporCB();
    25.         cbj.setUserCallBack(wcb);
    26.         cbj.process(300);
    27.         cbj.resetUserCallBack(wcb);
    28.     }
    29.     
    30. }
    阅读(1374) | 评论(0) | 转发(2) |
    给主人留下些什么吧!~~
    评论热议
  • 相关阅读:
    以下哪个Hibernate主键生成策略是实现主键按数值顺序递增的?
    编写一个Filter,除继承HttpServlet类外还需要( )。
    有关JSP隐式对象,以下( )描述正确。
    JAVA通信系列三:Netty入门总结
    JAVA通信系列二:mina入门总结
    JAVA通信系列一:Java Socket技术总结
    大型网站架构系列:缓存在分布式系统中的应用(三)
    大型网站架构系列:缓存在分布式系统中的应用(二)
    大型网站架构系列:缓存在分布式系统中的应用(一)
    大型网站架构系列:负载均衡详解(4)
  • 原文地址:https://www.cnblogs.com/black/p/5171796.html
Copyright © 2011-2022 走看看