jni调用java方法,该方法将自定义java接口作为参数 [英] jni call java method which take a custom java interface as parameter

查看:217
本文介绍了jni调用java方法,该方法将自定义java接口作为参数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在研究cocos2d-x平台上的一个插件项目,我想编写一些c ++包装器接口来通过 JNI jar SDK。我知道如何使用JNI来调用静态java方法,但我对java函数中的interface参数感到困惑。
我有一个处理回调的cpp函数指针:

I'm working on a plugin project on cocos2d-x platform , I'd like to write some c++ wrapper interface to invoke java method through JNI from jar SDK . I know how to use JNI to invoke a static java method, but I'm confused by the interface parameter in the java function. I hava a cpp function pointer to handling callbacks:

typedef void (* MyCallback)(int responseCode, string arg1, set<string> arg2);

我想编写一个cpp包装器方法,如:

and I want to write a cpp wrapper method like :

static void MyCpp::setTags(set<string> tags, MyCallback callback) //it use `JNI` to invoke java method setTags(Context context, Set<String> tags, TagCallback callback).

我想在包装器中调用的java方法是

The java method I want to invoke in the wrapper is

public static void setTags(Context context, Set<String> tags, TagCallback callback)

TagCallback 是API用户要实现的接口。
那么,是否有可能获得 TagCallback 最终回调到 MyCallback 函数?换句话说,我可以使用 jni 将cpp函数指针转换为java接口吗?
感谢您的耐心等待。

and the TagCallback is an interface for API user to implement. So, is it possible to get TagCallback finally callback to MyCallback function? in other words , can I use jni to convert a cpp function pointer to java interface? Thanks for your patience .

编辑:
这里是如何使用 setTag 如果用户只想使用java:

here is how to use setTag if user want to use java only:

public static void setTags(context, tags, new TagCallback{
    @Override
    public void callback(int arg0, String arg1, Set<String> arg2) {
            // TODO Auto-generated method stub
        }
})

我希望我的SDK用户能够像我这样使用我的cpp包装器方法:

I'd like my SDK user to use my cpp wrapper method like this:

void setTagCallback(int responseCode, string arg1, set<string> arg2){
   //users handle callback themselves.
}

void someOtherMethodInvokeTheCppWrapperMethod(){
    MyCallback callback = setTagCallback;
    set<string> tags;
    MyCpp::setTags(tags,callback); 
}


推荐答案

首先你需要构建一个可以在TagCallback兼容基类中包装本机C ++函数指针的类:

Well firstly you'll need to build a class that can wrap the native C++ function pointer in a TagCallback compatible base class:

public class NativeTagCallback : TagCallback
{
    protected long      cppCallbackPtr;

    public NativeTagCallback( long callbackPtr )
    {
        cppCallbackPtr = callbackPtr;
    }

    public native void NativeCallback( long callbackPtr, int arg0, String arg1, Set<String> arg2 );

    public void callback(int arg0, String arg1, Set<String> arg2) 
    {
        NativeCallback( cppCallbackPtr, arg0, arg2, arg2 );
    }
}

本机代码定义如下:

extern "C" jvoid Java_com_wrapper_NativeTagCallback_NativeCallback( JNIEnv* pEnv, jobject jCaller, jlong cppCallbackPtr, jint arg0, jstring arg1, jobject arg2 )
{
    MyCallback cppCallback = (MyCallback)cppCallbackPtr;
    const char* pCString = pEnv->GetStringUTFChars( arg1, 0);
    string arg1Str( pCString );
    pEnv->ReleaseStringUTFChars( arg1, pCString );

    set< string > arg2Set = ConvertJavaSetToCPPSet( arg2 );  // Perform your java to CPP set conversion here.

    cppCallbackPtr( (int)arg0, arg1Str, arg2Set );
}

然后你将创建相关的类并将其从C ++传递给你的函数as如下:

Then you would create the relevant class and pass it to your function from C++ as follows:

void MyCpp::setTags(set<string> tags, MyCallback callback)
{
    extern __thread JNIEnv* gpEnv;

    // Get the setTags function.
    jclass      jWrapperClass                   = gpEnv->FindClass( "com/wrapper/cocoswrapper" ); // Insert the correct class name here.    
    jmethodID   jWrapperSetTag                  = gpEnv->GetStaticMethodID( jWrapperClass, "setTags", "(Landroid/content/Context;Ljava/util/Set;Lcom/wrapper/TagCallback)V;" );

    // Get the TagCallback related function
    jclass      jNativeTagCallbackClass         = gpEnv->FindClass( "com/wrapper/NativeTagCallback" );
    jclass      jNativeTagCallbackConstructor   = gpEnv->GetMethodID( jNativeTagCallbackClass, "<init>", "(J)V" );
    jobject     jNativeTagCallbackObject        = gpEnv->NewObject( jNativeTagCallbackClass, jNativeTagCallbackConstructor, (jlong)callback)

    // Make function call.
    gpEnv->CallStaticVoidMethod( jWrapperClass, jWrapperSetTag, jAndroidContext, tags.GetJNIObject(), jNativeTagCallbackObject );
}

这篇关于jni调用java方法,该方法将自定义java接口作为参数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆