JNI实现JAVA和C++互相调用

SDK.h

 1 #ifndef SDK_H
 2 #define SDK_H
 3 
 4 #include "AsyncProxy.h"
 5 #include "Module.h"
 6 #include <map>
 7 #include <vector>
 8 #include <string>
 9 using std::map;
10 using std::vector;
11 using std::string;
12 
13 
14 class SDK
15 {
16 private:
17     vector<Module*> m_modules;
18     AsyncProxy* mp_asyncProxy;
19     map<string,Method*> m_methodIndex;
20 private:
21     Method* checkMethod(string methodName, map<std::string, std::string> &params);
22     void init();
23 public:
24     SDK();
25     SDK(CallBackFun* p_exceptionFun);
26     ~SDK();
27     void addModule(Module* p_module);
28     string request(string methodName, map<string,string>& params);
29     void requestAsync(string methodName, map<string, string> &params, CallBackFun* p_callBack = NULL);
30 };
31 
32 #endif

CallBackFun.h

1 class CallBackFun
2 {
3 public:
4     virtual ~CallBackFun(){}
5     virtual void callBack(string& result){SDK_DEBUG("%s",result.c_str());}
6 };

main.cpp

#include <string.h>
#include <jni.h>
#include "core/SDK.h"

static JavaVM* p_vm = NULL;

JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void* reserved)
{
    p_vm = vm;
    return JNI_VERSION_1_6;
}

class JavaCallBackFun:public CallBackFun
{
private:
    jobject m_object;
    jstring m_method;
    static const char* m_signature;
    bool m_destroy;
public:
    JavaCallBackFun( JNIEnv* env,jobject object,jstring method,bool destroy)
    {
        m_object = env->NewGlobalRef(object);
        m_method = (jstring)env->NewGlobalRef(method);
        m_destroy = destroy;
    }
    
    ~JavaCallBackFun()
    {
        if(m_destroy == false)
        {
            JNIEnv* env;
            p_vm->AttachCurrentThread(&env, NULL);
            env->DeleteGlobalRef(m_object);
            env->DeleteGlobalRef(m_method);
        }
    }
    
    void callBack(string& result)
    {
        JNIEnv* env;
        p_vm->AttachCurrentThread(&env, NULL);
        jstring jresult = env->NewStringUTF(result.c_str());
        const char* methodStr = env->GetStringUTFChars(m_method, 0);
        jclass clazz = env->GetObjectClass(m_object);
        jmethodID  methodID = env -> GetMethodID(clazz,methodStr,m_signature);
        env -> CallVoidMethod(m_object,methodID,jresult);
        env -> ReleaseStringUTFChars(m_method,methodStr);
        if(m_destroy == true)
        {
            env->DeleteGlobalRef(m_object);
            env->DeleteGlobalRef(m_method);
        }
    }
};
const char* JavaCallBackFun::m_signature = "(Ljava/lang/String;)V";



extern "C" {
    JNIEXPORT jlong JNICALL Java_com_pptv_sdk_CommonSDK_initSDKNative( JNIEnv* env,jobject thiz,jobject callBackObj,jstring exceptionFun);
    JNIEXPORT void JNICALL Java_com_pptv_sdk_CommonSDK_cleanSDKNative( JNIEnv* env,jobject thiz,jlong sdkptr);
    JNIEXPORT jstring JNICALL Java_com_pptv_sdk_CommonSDK_requestNative( JNIEnv* env,jobject thiz,jlong sdkptr,jstring methodName,
                                                                         jobjectArray paramKeys,jobjectArray paramValues);
    JNIEXPORT void JNICALL Java_com_pptv_sdk_CommonSDK_requestAsyncNative( JNIEnv* env,jobject thiz,jlong sdkptr,jstring methodName,
                                                jobjectArray paramKeys,jobjectArray paramValues,jobject callBackObj,jstring callBackMethod);
};

JNIEXPORT jlong JNICALL Java_com_pptv_sdk_CommonSDK_initSDKNative( JNIEnv* env,jobject thiz,jobject callBackObj,jstring exceptionFun)
{
    JavaCallBackFun* p_callBack = new JavaCallBackFun(env,callBackObj,exceptionFun,false);
    return (jlong)new SDK(p_callBack);
}

JNIEXPORT void JNICALL Java_com_pptv_sdk_CommonSDK_cleanSDKNative( JNIEnv* env,jobject thiz,jlong sdkptr)
{
    SDK* p_sdk = (SDK*)sdkptr;
    delete p_sdk;
}

JNIEXPORT jstring JNICALL Java_com_pptv_sdk_CommonSDK_requestNative( JNIEnv* env,jobject thiz,jlong sdkptr,jstring methodName,
                                                                     jobjectArray paramKeys,jobjectArray paramValues)
{
    SDK* p_sdk = (SDK*)sdkptr;
    const char * methodNameStr = env->GetStringUTFChars( methodName, 0);
    //init param map
    jstring jkey,jvalue;
    jsize keysLen=env->GetArrayLength(paramKeys);
    map<string,string> params;
    for(jsize i=0;i<keysLen;++i)
    {
        jkey = (jstring)(env->GetObjectArrayElement(paramKeys,i));
        jvalue = (jstring)(env->GetObjectArrayElement(paramValues,i));
        const char *key = env->GetStringUTFChars(jkey, 0);
        const char *value = env->GetStringUTFChars(jvalue,0);
        params[string(key)] = string(value);
        env->ReleaseStringUTFChars(jkey,key);
        env->ReleaseStringUTFChars(jvalue,value);
    }
    
    string result = p_sdk->request(methodNameStr,params);
    env->ReleaseStringUTFChars(methodName,methodNameStr);
    return env->NewStringUTF(result.c_str());
}

JNIEXPORT void JNICALL Java_com_pptv_sdk_CommonSDK_requestAsyncNative( JNIEnv* env,jobject thiz,jlong sdkptr,jstring methodName,
                                            jobjectArray paramKeys,jobjectArray paramValues,jobject callBackObj,jstring callBackMethod)
{
    SDK* p_sdk = (SDK*)sdkptr;
    const char * methodNameStr = env->GetStringUTFChars(methodName, 0);
    //init param map
    jstring jkey,jvalue;
    jsize keysLen=env->GetArrayLength(paramKeys);
    map<string,string> params;
    for(jsize i=0;i<keysLen;++i)
    {
        jkey = (jstring)(env->GetObjectArrayElement(paramKeys,i));
        jvalue = (jstring)(env->GetObjectArrayElement(paramValues,i));
        const char *key = env->GetStringUTFChars(jkey, 0);
        const char *value = env->GetStringUTFChars(jvalue,0);
        params[string(key)] = string(value);
        env->ReleaseStringUTFChars(jkey,key);
        env->ReleaseStringUTFChars(jvalue,value);
    }
    //init callback fun
    JavaCallBackFun* p_callBack = NULL;
    if(callBackObj != NULL && callBackMethod != NULL)
    {
        p_callBack = new JavaCallBackFun(env,callBackObj,callBackMethod,true);
    }
    //async call 
    p_sdk->requestAsync(methodNameStr,params,p_callBack);
    env->ReleaseStringUTFChars(methodName,methodNameStr);
}

CommonSDK.java

 1 package com.pptv.sdk;
 2 import java.util.Map;
 3 
 4 /**
 5  * CommonSDK is a common interface to interact with sdk.so
 6  * <p>
 7  * CommonSDK use jni to call native method written by C++,and it 
 8  * provide a common interface for Java developer.You can directly
 9  * call the common interface,but it is suggested to use the special
10  * interface based on CommonSDK,which is more understandable.  
11  * @author      guoxiaoqian
12  */
13 public class CommonSDK implements SDKCallBack
14 {
15     static
16     {
17         System.loadLibrary("sdk");
18     }
19     
20     //Exception Call Back
21     @Override
22     public void callBack(String result)
23     {
24         // TODO Auto-generated method stub
25         System.out.println("Exception occured: "+result);
26     }
27     
28     private long m_sdkHandle;
29     private static final CommonSDK m_sdk = new CommonSDK();
30     
31     private CommonSDK()
32     {
33         m_sdkHandle = initSDKNative(this,SDKCallBack.callBackName);
34     }
35     
36     
37     /** 
38      * getInstance()     get a singleton CommonSDK object
39      * @return          CommonSDK object
40      */
41     public static CommonSDK getInstance()
42     {
43         return m_sdk;
44     }
45     
46     protected void finalize()
47     {
48         cleanSDKNative(m_sdkHandle);
49     }
50     
51     /** 
52      * request()             sync request
53      * @param methodName    specify the method to call
54      * @param params        multi params in key-value map
55      * @return              json string containing complex result
56      */
57     public String request(String methodName,Map<String,String> params)
58     {
59         String[] keyArr = new String[params.size()];
60         String[] valueArr = new String[params.size()];
61         int i=0;
62         for(Map.Entry<String, String> entry:params.entrySet())
63         {    
64             keyArr[i] = entry.getKey();
65             valueArr[i] = entry.getValue();
66             ++i;
67         }
68         return requestNative(m_sdkHandle,methodName,keyArr,valueArr);
69     }
70     
71     /** 
72      * requestAsync()         async request
73      * @param methodName    specify the method to call
74      * @param params        multi params in key-value map
75      * @param callBackObj    specify the obj to handle callback from sdk
76      */
77     public void requestAsync(String methodName,Map<String,String> params,SDKCallBack callBackObj)
78     {
79         String[] keyArr = new String[params.size()];
80         String[] valueArr = new String[params.size()];
81         int i=0;
82         for(Map.Entry<String, String> entry:params.entrySet())
83         {    
84             keyArr[i] = entry.getKey();
85             valueArr[i] = entry.getValue();
86             ++i;
87         }
88         requestAsyncNative(m_sdkHandle,methodName,keyArr,valueArr,callBackObj,callBackObj==null?null:SDKCallBack.callBackName);
89     }
90     
91     private native long initSDKNative(Object callBackObject,String exceptionFun);
92     private native void cleanSDKNative(long sdkHandle);
93     private native String requestNative(long sdkHandle,String methodName,String keys[],String values[]);
94     private native void requestAsyncNative(long sdkHandle,String methodName,String keys[],String values[],Object callBackObject,String callBackFunName);
95 
96 }

SDKCallBack.java

 1 package com.pptv.sdk;
 2 
 3 /**
 4  * SDKCallBack is an interface that you must implements when
 5  * you want to have an object to handle the callback form sdk.
 6  * @author      guoxiaoqian
 7  */
 8 public interface SDKCallBack {
 9     public final String callBackName = "callBack";
10     public abstract void callBack(String result);
11 }
原文地址:https://www.cnblogs.com/guoxiaoqian/p/3915429.html