Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/154.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
Java C++/JNI—向量和数组中的存储对象(jobject)意外更改,C++;还是JNI问题?_Java_C++_Lambda_Java Native Interface_Squirrel - Fatal编程技术网

Java C++/JNI—向量和数组中的存储对象(jobject)意外更改,C++;还是JNI问题?

Java C++/JNI—向量和数组中的存储对象(jobject)意外更改,C++;还是JNI问题?,java,c++,lambda,java-native-interface,squirrel,Java,C++,Lambda,Java Native Interface,Squirrel,因此,首先是一些背景: 我一直在用JNI,特别是松鼠脚本语言为java包C++库。当我需要将本机函数传递给Squirrel虚拟机时,问题就出现了。Squirrel要求一个函数是SQFUNCTION,该函数定义为一个以HSQUIRRELVM为参数并返回SQInteger的函数,但请记住,我正在为Java包装这个函数。我可以让C++从JOBEDIT调用java方法,但是我需要在lambda函数中封装这个调用,以便将它实际传递给松鼠。通常我会将[=]作为lambda捕获,这样它就可以引用我的变量,但由

因此,首先是一些背景:

我一直在用JNI,特别是松鼠脚本语言为java包C++库。当我需要将本机函数传递给Squirrel虚拟机时,问题就出现了。Squirrel要求一个函数是SQFUNCTION,该函数定义为一个以HSQUIRRELVM为参数并返回SQInteger的函数,但请记住,我正在为Java包装这个函数。我可以让C++从JOBEDIT调用java方法,但是我需要在lambda函数中封装这个调用,以便将它实际传递给松鼠。通常我会将[=]作为lambda捕获,这样它就可以引用我的变量,但由于某些原因,我完全不确定,捕获变量会改变lambda函数的类型,它不再被识别为sq函数。我最近决定用常量向量或数组来解决这个问题,这样lambda就可以访问它。我告诉Squirrel对象存储在向量/数组中的什么位置,并让lambda从Squirrel获取该值以访问它。问题是:在正确的插槽中有一个对象,但它不是我放在那里的对象

问题是我对C++和JNI没有太多的经验,我没有搜索过的东西告诉我这是什么问题。我尝试过存储对象和指向对象的指针,但这两种方法的结果是相同的。我正在存储
JSqTestFunc
的一个实例,但代码正在检索
JSqVM
的一个实例。除了与Squirrel交互之外,这两个类唯一的共同点是它们扩展了对象,否则它们是完全不相关的

我想我的问题应该分为多个部分:

这是C++问题还是JNI问题?<李>
  • 我怎样才能解决这个问题
  • 我觉得它必须是JNI问题,但我也不能排除C++对我来说是愚蠢的。我不熟悉JNI如何处理jobject类及其引用,因此jobject最终可能会在内部存储另一个类的数据。我在C++数组和向量存储中也没有发现任何与此相关的问题。

    C++函数看起来是这样的:

    static const int m_maxClosures = 8;
    static int m_closures = 0;
    
    static JNIEnv *m_envs[m_maxClosures];
    static jobject m_objs[m_maxClosures];
    
    JNIEXPORT void JNICALL Java_com_yourlocalfax_jsquirrel_Squirrel_sq_1newclosure_1native(JNIEnv *env, jclass c, jlong vmhandle, jobject func, jlong nfreevars) {
        HSQUIRRELVM v = fromPointerHandleToObject<HSQUIRRELVM>(vmhandle);
    
        int idx = m_closures;
    
        printf("Creating number %d closure of %d", idx, m_maxClosures);
    
        m_closures++;
    
        m_envs[idx] = env;
        m_objs[idx] = func;
    
        sq_pushinteger(v, idx);
    
        JNIEnv *e = m_envs[idx];
        jobject o = m_objs[idx];
    
        jobject clsObj = e->CallObjectMethod(o, e->GetMethodID(e->GetObjectClass(o), "getClass", "()Ljava/lang/Class;"));
        jstring strObj = (jstring)e->CallObjectMethod(clsObj, e->GetMethodID(e->GetObjectClass(clsObj), "getName", "()Ljava/lang/String;"));
    
        const char* str = e->GetStringUTFChars(strObj, NULL);
        printf("\nInitial calling class is: %s\n", str);
        e->ReleaseStringUTFChars(strObj, str);
    
        SQFUNCTION f = [](HSQUIRRELVM v) {
            print_args(v);
            squirrel_stack_trace(v);
    
            SQInteger i;
    
            sq_pushinteger(v, 0); // Push the index in the table TO GET
            sq_get(v, 1); // Push the index of the actual table
            sq_getinteger(v, -1, &i); // Get the newly pushed value (integer)
            //sq_getinteger(v, 2, &i);
            printf("Location Id is %d of %d", i, m_maxClosures);
    
            JNIEnv *e = m_envs[i];
            jobject o = m_objs[i];
    
            jobject clsObj = e->CallObjectMethod(o, e->GetMethodID(e->GetObjectClass(o), "getClass", "()Ljava/lang/Class;"));
            jstring strObj = (jstring)e->CallObjectMethod(clsObj, e->GetMethodID(e->GetObjectClass(clsObj), "getName", "()Ljava/lang/String;"));
    
            const char* str = e->GetStringUTFChars(strObj, NULL);
            printf("\nCalling class is: %s\n", str);
            e->ReleaseStringUTFChars(strObj, str);
    
            jclass cls = e->GetObjectClass(o);
            jmethodID m = e->GetMethodID(cls, "function", "(Lcom/yourlocalfax/jsquirrel/JSqVM;)I");
            //sq_pushinteger(v, e->CallIntMethod(o, m));
            return (SQInteger)0;
        };
    
        sq_newclosure(v, f, nfreevars + 1);
    }
    
    如您所见,jobject数组的索引0最初存储一个
    JSqTestFunc
    ,但在检索时存储一个
    JSqVM


    任何帮助,即使是一种不同的方法,都是非常感激的,因为我花了太长时间和太多的精力试图解决这个问题。谢谢

    在发布这篇文章之后,我继续深入研究,并意识到这确实是JNI方面与本地和全局引用相关的一个问题。我所要做的就是
    env->NewGlobalRef(object)然后将对象存储在数组中。这就解决了问题

    我将把这个问题留下来回答,以防将来对任何人都有帮助

    Creating number 0 closure of 8
    Initial calling class is: com.yourlocalfax.jsquirrel.test.JSqTestFunc
    Location Id is 0 of 8
    Calling class is: com.yourlocalfax.jsquirrel.JSqVM