1. 程式人生 > >C++回撥函式呼叫Java介面抽象函式

C++回撥函式呼叫Java介面抽象函式

專案中很多程式碼採用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進行加密,加密函式為回撥函式。標頭檔案定義如下

#ifdef CALLBACK_EXPORTS
#define CALLBACK_API __declspec(dllexport)
#else
#define CALLBACK_API __declspec(dllimport)
#endif

#ifdef __cplusplus
extern "C"
{
#endif
    typedef int (*UserProcess)(int nEncrptType);
    CALLBACK_API int Process(UserProcess cb,

int nCompanID);
#ifdef __cplusplus
}
#endif

其實現檔案為

#include "stdafx.h"
#include "CallBack.h"


CALLBACK_API int Process(UserProcess cb,int nCompanID)
{
    if(cb == NULL)
    {
        return -1;
    }

    cb(nCompanID);
    return 0;
}

2.C++語言使用回撥函式庫
用法比較簡單,直接實現一個滿足UserProcess定義的函式,然後將其傳遞給Process函式即可,見下文程式碼內容。

#

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

int WanporProcess(int i)
{
    printf("Process = %d\n",i);
    return i;
}
int _tmain(int argc, _TCHAR* argv[])
{

    Process(WanporProcess,100);
    return 0;
}

加密函式將公司ID直接輸出,未進行其他處理。
3.Java語言使用回撥函式
這個過程相對於C++顯得比較繁瑣,主要包含以下一個過程:
3.1編寫回調函式的抽象介面,並實現一個回撥類;
3.2在JNI中安裝回調介面類
3.3實現C++的回撥函式,在此回撥函式中獲取抽象介面類物件、回撥函式的介面名稱、呼叫回撥函式
3.4呼叫process進行回撥函式執行
2.5解除安裝回撥類
下面依次實現上述中的內容
3.1回撥函式介面定義

package cn.com.wanpor;
//編寫回調函式介面

public interface CBInterface{
    public abstract int UserProcess(int encryptType);
}

3.2實現回撥類

//實現回撥類

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

3.3C++ JNI程式碼中安裝回調類

#include "stdafx.h"
#include "../CallBack/CallBack.h"
#include "cn_com_wanpor_CallBackJNI.h"

typedef struct CBData{
    UserProcess m_pfnUserProcess;
    jobject m_objInterface;
    JNIEnv* m_pEnv;
    jobject m_objCallBack;
}CBData;

CBData g_cbData;
JNIEXPORT jint JNICALL Java_cn_com_wanpor_CallBackJNI_setUserCallBack
(JNIEnv * env, jobject obj, jobject cb)
{
    
    g_cbData.m_pEnv = env;
    g_cbData.m_objCallBack = env->NewGlobalRef(obj);
    g_cbData.m_objInterface = env->NewGlobalRef(cb);

    return 0;
}

3.4實現C++回撥函式

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

    jclass jclsProcess = g_cbData.m_pEnv->GetObjectClass(g_cbData.m_objInterface);
    if (jclsProcess == NULL)
    {
        printf("jclsProcess = NULL\n");
        return -1;
    }
    jmethodID jmidProcess = g_cbData.m_pEnv->GetMethodID(jclsProcess,"UserProcess","(I)I");
    if (jmidProcess == NULL)
    {
        printf("jmidProcess = NULL\n");
        return -2;
    }

    g_cbData.m_pEnv->CallIntMethod(g_cbData.m_objInterface,jmidProcess,nEncrpytType);
    
    pVm->DetachCurrentThread();
    
    return 0;
}

3.5執行回撥函式

JNIEXPORT jint JNICALL Java_cn_com_wanpor_CallBackJNI_process
(JNIEnv * env, jobject obj, jint nCompanyID)
{
    Process(ProcessJNICB,nCompanyID);
    return 0;
}

3.6解除安裝回撥類

JNIEXPORT jint JNICALL Java_cn_com_wanpor_CallBackJNI_resetUserCallBack
(JNIEnv * env, jobject objCallBack, jobject objInterface)
{
    g_cbData.m_pEnv->DeleteGlobalRef(objInterface);
    g_cbData.m_pEnv->DeleteGlobalRef(objCallBack);
    return 0;
}

4.Java測試程式
下面的程式碼是對JNI介面的測試程式,WanporCB實現了回撥介面,回撥函式返回值為0,但打印出3*nCompany的值,程式執行函式的順序是:
建立回撥函式介面例項
建立測試物件
安裝回調類
執行加密
解除安裝回撥類
程式碼如下:

package cn.com.wanpor;

//實現回撥類

class WanporCB implements CBInterface {
    public int UserProcess(int encryptType){
        System.out.println("Java = " + 3*encryptType);
        return 0;
    }
}
public class CallBackJNI{
    static{
        System.load("E:\\Program Files\\Java\\jdk1.5.0_15\\bin\\CallBackJNI.dll");
    }
    
    //設定回撥函式

    public native int setUserCallBack(CBInterface cb);
    //清除回撥函式

    public native int resetUserCallBack(CBInterface cb);
    //執行使用者自定義加密

    public native int process(int companyID);
    
    //測試程式

    public static void main(String[] argv){
        CallBackJNI cbj = new CallBackJNI();
        WanporCB wcb = new WanporCB();
        cbj.setUserCallBack(wcb);
        cbj.process(300);
        cbj.resetUserCallBack(wcb);
    }
    
}

相關推薦

C++函式呼叫Java介面抽象函式

專案中很多程式碼採用C++編寫,配置介面則採用BS結構,使用Java語言進行設定。因此需要實現Java呼叫C++編寫的函式庫(dll檔案或so檔案),採用的技術為JNI(Java Native Interface),對於常用的呼叫方式在《The Java Native In

c函式java抽象函式介面函式抽象類簡單理解

先了解c語言的回撥函式,舉個簡單例項步步深入,比如A程式提供給B程式使用,但是A想要呼叫B的程式碼,這樣各自不同功能由B實現即可。 例項1A: extern int get_B_data(); void A_data_handle(){ printf("%d\n",get

JNI實現| JNI呼叫JAVA函式|引數和返回值的格式

程式碼下載:http://dl.dbank.com/c0c0xs3b24 一、JNI實現回撥 通過JNI在Native層呼叫Java層的方法,來實現Native層向JAVA層傳遞訊息。 JNICallback.java publicclass JNICallback e

C++虛擬函式JAVA抽象函式比較 介面抽象類比較

C++虛擬函式與Java中抽象函式比較 1:java中沒有虛擬函式的概念,但是有抽象函式的概念,用abstract關鍵字表示,java中抽象函式必須在抽象類中,而且抽象 函式不能有函式體,抽象類不能被例項化,只能由其子類實現抽象函式,如果某個抽象類的子類仍是抽象類,那麼該子

Andriod JNI程式設計之C++Java函式

一般我們NDK程式設計都是Java層呼叫C++的介面,但其實才C++層也可以呼叫Java的函式。實現方法如下: 1、獲取類名:jclass cls = env->FindClass 2、獲取類方法:jmethodID mid = env->GetMethodID

C++函式

摘要:回撥函式就是一個通過函式指標呼叫的函式。如果你把函式的指標(地址)作為引數傳遞給另一個函式,當這個指標被用來呼叫其所指向的函式時,我們就說這是回撥函式。回撥函式不是由該函式的實現方直接呼叫,而是在特定的事件或條件發生時由另外的一方呼叫的,用於對該事件或條件進行響應。

轉:C++函式

     今天討論下C/C++中的回撥函式。      在理解“回撥函式”之前,首先討論下函式指標的概念。 函式指標 (1)概念:指標是一個變數,是用來指向記憶體地址的。一個程式執行時,所有和執行相關的物件都是需要載入到記憶體中,這就決定了程式執行時的任何物件都可以

淺析c#函式用法

最近剛接觸到回撥函式,網上找了找解釋,感覺不是很明白,在專案中看到了回撥函式的實際用法,那就是回撥函式的提供者並不呼叫這個函式,而是把這個函式地址作為引數,傳遞給自己呼叫的其它方法的引數。所以回撥函式是要呼叫的函式不知

C++函式用法

一回調函式 我們經常在C++設計時通過使用回撥函式可以使有些應用(如定時器事件回撥處理、用回撥函式記錄某操作進度等)變得非常方便和符合邏輯,那麼它的內在機制如何呢,怎麼定義呢?它和其它函式(比如鉤子函式)有何不同呢? 使用回撥函式實際上就是在呼叫某個函式(通常是API函式)時,將自己的一個函式(這個函式為回

C/C++方式系列之二class介面和lambda程式

在《C/C++回撥方式系列之一》中我們總結了函式指標模式回撥,這些回調當時比較原始,容易給人一種面向過程的程式設計的感覺,而且函式指標的格式比較繁瑣,可讀性相對差一點。本系列二將總結比較推薦的回撥使用模式。 一、class介面回撥模式 1. 定義介面 C++可以定義virt

C++ 函式理解

http://blog.csdn.net/clirus/article/details/50350519程式設計中肯定會遇到在C++中使用回撥函式的情況。但是為什麼要使用回撥函式呢?我們需要理解回撥函式設計原理因為可以把呼叫者與被呼叫者分開。呼叫者不關心誰是被呼叫者,所有它需

c++函式 callback

                                                                      C++中實現回撥機制的幾種方式(1)Callback方式 Callback的本質是設定一個函式指標進去,然後在需要需要觸發某個事件時

c++函式/ROS函式

以下均是個人在實際耕碼的過程中遇到的問題和整理的結果,可能會有不對的地方,望各位指正與交流 ------------------------------------------------------------------我會有喵的--------------------

淺談C/C++函式(Callback)& 函式指標

摘要:回撥函式就是一個通過函式指標呼叫的函式。如果你把函式的指標(地址)作為引數傳遞給另一個函式,當這個指標被用來呼叫其所指向的函式時,我們就說這是回撥函式。回撥函式不是由該函式的實現方直接呼叫,而是在特定的事件或條件發生時由另外的一方呼叫的,用於對該事件或條件進行響應。

C++函式跨模組

#ifndef CONTROLLER_H #define CONTROLLER_H // // 檔名:Controller.h // 工程名:CppCallback // 開發環境:MacOS 10.13.1 Qt5.9.1 // 簡介:回撥函式使用 // 建

C++函式的一點理解

回撥函式是通過函式指標呼叫的函式:把函式的指標(地址)作為引數傳遞給另一個函式,當這個指標被用來呼叫其所指向的函式時,就稱為回撥函式。回撥函式不是由該函式的實現方直接呼叫,而是在特定的事件或條件發生時由另外的一方呼叫的,用於對該事件或條件進行響應。 通俗點說就是:在A類中

Android 在使用介面呼叫 Thread.Sleep() 引發的思考

寫這篇文章的原因 原本只是想用最簡單最容易理解的方式去介紹在 Android 中如何使用介面回撥機制。剛開始我也覺得介面回撥也很朦朧,只知道是為了處理任務非同步,以及能使程式碼看起來更加容易理解和維護,但是如何去實現還不太清楚。 通過看了其他大神的部落格,終

C++函式的基本理解和使用

回撥函式就是一個通過函式指標呼叫的函式。如果你把函式的指標(地址)作為引數傳遞給另一個函式,當這個指標被用來呼叫其所指向的函式時,我們就說這是回撥函式。回撥函式不是由該函式的實現方直接呼叫,而是在特定的事件或條件發生時由另外的一方呼叫的,用於對該事件或條件進行響

淺談C++函式

  1.什麼是回撥函式?       回撥函式就是一個通過函式指標呼叫的函式。如果你把函式的指標(地址)作為引數傳遞給另一個函式,當這個指標被用來呼叫其所指向的函式時,我們就說這是回撥函式。回撥函式不是由該函式的實現方直接呼叫,而是在特定的事件或條件發生時由另外的一方呼叫的,

C++函式的理解與使用

一、回撥函式就是一個通過函式指標呼叫的函式。如果你把函式的指標(地址)作為引數傳遞給另一個函式,當這個指標被用來呼叫其所指向的函式時,我們就說這是回撥函式。回撥函式不是由該函式的實現方直接呼叫,而是在特定的事件或條件發生時由另外的一方呼叫的,用於對該事件或條件進行響應。 回撥函式機制: 1