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);
我希望我的SDK用户使用我的cpp包装器方法,如下所示: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
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);
}
在 一旦你有了<代码>的回调指针,你就可以将它投到C++函数指针并调用它。
要使用适配器类,在
中,可以使用JNIMyCpp::setTags
、FindClass()
和GetMethodID()
创建NewObject()
的实例,将NativeTagCallback
(long)(void*)回调作为
传递给构造函数。(这假设编译器生成可以容纳64位的函数指针。对于自由函数指针(相对于方法指针)来说,这通常是正确的,但值得使用快速测试程序进行检查。)然后将该实例作为其“回调”参数传递给Javacb
方法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 );
}