Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/383.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
jni调用以自定义java接口为参数的java方法 我在COCOS2D-X平台上开发了一个插件项目,我想编写一些C++包装接口来调用java方法,通过 jnI/Stand >从代码> jar >代码> SDK。我知道如何使用JNI调用静态java方法,但我对java函数中的接口参数感到困惑。 我有一个处理回调的cpp函数指针: typedef void (* MyCallback)(int responseCode, string arg1, set<string> arg2);_Java_Android_C++_Java Native Interface_Cocos2d X - Fatal编程技术网

jni调用以自定义java接口为参数的java方法 我在COCOS2D-X平台上开发了一个插件项目,我想编写一些C++包装接口来调用java方法,通过 jnI/Stand >从代码> jar >代码> SDK。我知道如何使用JNI调用静态java方法,但我对java函数中的接口参数感到困惑。 我有一个处理回调的cpp函数指针: typedef void (* MyCallback)(int responseCode, string arg1, set<string> arg2);

jni调用以自定义java接口为参数的java方法 我在COCOS2D-X平台上开发了一个插件项目,我想编写一些C++包装接口来调用java方法,通过 jnI/Stand >从代码> jar >代码> SDK。我知道如何使用JNI调用静态java方法,但我对java函数中的接口参数感到困惑。 我有一个处理回调的cpp函数指针: typedef void (* MyCallback)(int responseCode, string arg1, set<string> arg2);,java,android,c++,java-native-interface,cocos2d-x,Java,Android,C++,Java Native Interface,Cocos2d X,我希望我的SDK用户使用我的cpp包装器方法,如下所示: void setTagCallback(int responseCode, string arg1, set<string> arg2){ //users handle callback themselves. } void someOtherMethodInvokeTheCppWrapperMethod(){ MyCallback callback = setTagCallback; set<s

我希望我的SDK用户使用我的cpp包装器方法,如下所示:

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); 
}
void setTagCallback(int-responseCode,字符串arg1,集arg2){
//用户自己处理回调。
}
void someOtherMethodInvokeTheCppWrapperMethod(){
MyCallback callback=setTagCallback;
设置标签;
MyCpp::setTags(标记,回调);
}
就这样(请耐心听我说,我希望我讲得通) 我从Cocos2dx的“CCHttpRequest”库中得到了这个想法

在JNI类中,保留回调的映射

典型的JNI调用是(首先是同步调用,这是一种非常简单的方法)

调用者将发送类似>>>的内容,即callfuncND\u选择器(XyzClass::abcAction)

现在对于异步调用,上述函数将更改为

                    .
                    .
                    .
                    t.env->CallStaticVoidMethod(t.classID, t.methodID, itemId, uniqueId);
                    t.env->DeleteLocalRef(t.classID);
                  }
现在,在上面这个JNI调用的回调函数中

说出方法>>>

               JNIEXPORT void JNICALL Java_com_myproj_folder_AbcManager_callingAbcRequestCallback(JNIEnv*  env, jobject thiz, jstring data) {
                    const char * _data = env->GetStringUTFChars (data, 0);

                    //here we'll do the remaining work
                    //_data >>> is the Id of the callbackObject
                    //Get the Object from the Map for thie Id
                    // call this selector function
                    if (callbackObject->getTarget() && callbackObject->getSelector()) {
                    (callbackObject->getTarget()->*callbackObject->getSelector())(null, null); 
                    }
                    //Now you can delete the object and remove the map entry
        }
我们所做的是,我们创建了包含我们需要调用的函数的类,实现了一个接口,并将它们传递给JNI,然后从Java返回时,我们调用了我们使这些对象实现的方法


<>这也可以为您工作,但您仍然需要将它们放在一个映射中,以便您能够识别调用哪个对象的方法。

< P>我想您需要一个(私有)java类来实现TykCalbCad,它存储C++函数指针,实现Java+C++回调自适应:

private class NativeTagCallback implements TagCallback {
  private long _callbackPointer;

  private NativeTagCallback(long cb) { _callbackPointer = cb; }

  @Override
  public native void callback(int arg0, String arg1, Set<String> arg2);
}
私有类NativeTagCallback实现标记回调{
私有长回调指针;
私有的NativeTagCallback(长cb){u callbackPointer=cb;}
@凌驾
公共本机void回调(int arg0、字符串arg1、集arg2);
}

NATVETETAGCARBACK.CALBACK()/COD>中的C++实现中,您获取并转换参数 从java <代码>字符串和 SET//COD>对象到本机C++,然后使用JNI代码> GETFAREDIDER()/<代码>和<>代码> GEDLIGHORD()/<代码>函数,将<代码> >回调指针从 JOBJET ObjuttReals< /Cord>参数传递到JNI C++函数。

一旦你有了<代码>的回调指针,你就可以将它投到C++函数指针并调用它。 要使用适配器类,在

MyCpp::setTags
中,可以使用JNI
FindClass()
GetMethodID()
NewObject()
创建
NativeTagCallback
的实例,将
(long)(void*)回调作为
cb
传递给构造函数。(这假设编译器生成可以容纳64位的函数指针。对于自由函数指针(相对于方法指针)来说,这通常是正确的,但值得使用快速测试程序进行检查。)然后将该实例作为其“回调”参数传递给Java
setTags()
方法


保持
NativeTagCallback
私有非常重要,因为它可以用来调用任意地址!如果你想变得更加偏执,但更难调试,你可以把C++ ID保存到函数映射,只在NativeTagCallback > <代码>中存储ID。(这会将可调用的地址限制为当前正在使用的实际回调。IDS可以通过<代码>原生无效回调)()进行注册,但是映射需要线程安全。

< P>首先,您需要构建一个可以在TabelCouCube兼容的基类中封装本机C++函数指针的类:

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 );
    }
}
public类NativeTagCallback:TagCallback
{
受保护的长cppCallbackPtr;
公共本地回拨(长回拨PTR)
{
cppCallbackPtr=callbackPtr;
}
公共本机void NativeCallback(长callbackPtr,int arg0,字符串arg1,Set arg2);
公共无效回调(int arg0、字符串arg1、集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 );
}
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 );
}
extern“C”jvoid Java_com_包装器_NativeTagCallback_NativeCallback_NativeCallback(JNIEnv*pEnv、jobject jCaller、jlong cppccallbackptr、jint arg0、jstring arg1、jobject arg2)
{
MyCallback cppCallback=(MyCallback)cppCallbackPtr;
const char*pCString=pEnv->GetStringUTFChars(arg1,0);
字符串arg1Str(pCString);
pEnv->ReleaseStringUTFChars(arg1,pCString);
setarg2Set=ConvertJavaSetToCPPSet(arg2);//在此处执行java到CPP集的转换。
cppCallbackPtr((int)arg0、arg1Str、arg2Set);
}

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

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 );
}
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 );
}
void MyCpp::setTags(set tags,MyCallback)
{
外部线程JNIEnv*gpEnv;
//获取setTags函数。
jclass jWrapperClass=gpEnv->FindClass(“com/wrapper/cocoswrapper”);//在此处插入正确的类名。
jmethodID jWrapperSetTag=gpEnv->GetStaticMethodID(jWrapperClass,“setTags”,“(Landroid/content/Context;Ljava/util/Set;Lcom/wrapper/TagCallback)V;”;
//获取TagCallback相关函数
jclass jNativeTagCallbackClass=gpEnv->FindClass(“com/wrapper/NativeTagCallback”);
jclass jNativeTagCallbackConstructor=gpEnv->GetMethodID(jNativeTagCallbackClass,”,“(J)V”);
jobject jNativeTagCallbackObject=gpEnv->NewObject(jNativeTagCallbackClass,jNativeTagCallbackConstructor,(jlong)回调)
//进行函数调用。
gpEnv->CallStaticVoidMethod(jWrapperClass、jWrapperSetTag、jAndroidContext、tags.GetJNIObject()、jNativeTagCallbackObject);
}

请举例说明用户代码和th的调用顺序
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 );
}
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 );
}