初始化C++;JNI/Android中的一次对象

初始化C++;JNI/Android中的一次对象,android,opencv,java-native-interface,instantiation,Android,Opencv,Java Native Interface,Instantiation,我不熟悉Android和JNI的东西。但是在C/C++方面有丰富的经验。我正试图弄明白以下几点 将VS2013中的桌面代码移植到Android。这是一个opencv项目。 我已经移植了大部分性能代码。 但我无法理解如何初始化某些对象,并在某个处理步骤的生命周期内使它们保持活动状态 桌面代码的伪代码 vector<contours*> cntrs // Initialized somewhere else void ProcessFrame(Mat) { LOOP unti

我不熟悉Android和JNI的东西。但是在C/C++方面有丰富的经验。我正试图弄明白以下几点

将VS2013中的桌面代码移植到Android。这是一个opencv项目。 我已经移植了大部分性能代码。 但我无法理解如何初始化某些对象,并在某个处理步骤的生命周期内使它们保持活动状态

桌面代码的伪代码

vector<contours*> cntrs // Initialized somewhere else

void ProcessFrame(Mat)
{

    LOOP until kb != 'q'
    {
         step 1 - Extract contours and add them to vector<contours> 

         step 2 -  Display contours
    } 
}
vector cntrs//在其他地方初始化
空框(垫)
{
循环到kb!=“q”
{
步骤1-提取轮廓并将其添加到矢量
步骤2-显示轮廓
} 
}
在android中,我知道我可以将一个图像传递给C/C++代码处理它,然后将其返回给Java。 但我想要的是,我不想每次输入提取轮廓的主JNI函数时都初始化向量

是否有明确的方法/模式/技术来做到这一点


< >你的C++中的全局对象是合法的。您可以使用一些特殊的JNI调用来初始化它们,或者依赖于特定于JNI的JNI_OnLoad(),它保证在加载本机代码(共享对象,类似于Windows DLL的Android)后调用一次。您还可以让编译器处理此初始化,例如

std::vector<int> global_v  { 1, 1, 2, 3, 5, 8 };
C++(用NDK编译成libFILE.so)

JNIEXPORT jlong JNICALL Java_com_demo_FILE_fopen(JNIEnv*env、jclass cls、jstring fname、jstring fmode)
{
char*szfname=(*env)->GetStringUTFChars(env,fname,0);
char*szmode=(*env)->GetStringUTFChars(env,fmode,0);
FILE*f=fopen(szfname,szmode);
(*env)->ReleaseStringUTFChars(env、fmode、szmode);
(*env)->发布StringUTFChars(env、fname、szname);
retrun(jlong)(f);
}
JNIEXPORT jlong JNICALL Java_com_demo_文件_fputs(JNIEnv*env、jclass cls、jlong jf、jstring s)
{
char*szs=(*env)->GetStringUTFChars(env,s,0);
文件*f=重新解释(jf);
长透镜=fputs(f,sz);
(*env)->发布StringUTFChars(env、s、szs);
雷特伦;
}
JNIEXPORT void JNICALL Java_com_demo_FILE_fclose(JNIEnv*env,jclass cls,jlong jf)
{
文件*f=重新解释(jf);
fclose(f);
}

您的意思是,我可以将它们保留为全局变量,然后进行JNI调用来初始化它们。但更好的方法是调用JNI_Load()?在这种情况下,我仍然将它们保留在全球范围内?很抱歉,我的回答令人困惑。是的,在任何情况下,您都可以将全局对象保持为全局对象,因为通常JNI调用作用域的时间很短,并且JNI调用序列不共享某些特定的C/C++上下文。在决定是否使用JNI_OnLoad()或专有JNI调用,或全局作用域初始化时,没有通用的“更好”选项。选择取决于程序的性质。使用专有的JNI初始值设定项可以让Java更好地控制,例如,允许您随意重新初始化对象,即使库没有再次加载。但是如果您不需要这样的控制,那么其他两个选项更好,因为它们不需要额外的Java调用。解决了一个令人困惑的问题。我会试试这个。Cheers@typelogic:使用
std::vector
您不需要麻烦。你有一个全局向量对象,当数据到达时,你调整它的大小并填充它;您可以随时调整其大小并填充不同的数据(即使大小不同)。当它的时间到来时,它将被C++运行时释放。
package com.demo;
public class FILE {
  public void test1 {
    long file = fopen("/sdcard/test1", "w");
    fputs(file, "abc");
    fclose(file);
  }

  static { System.loadLibrary("FILE"); }
  private static native long fopen(String fname, String fmode);
  private static native long fwrite(long f, String s);
  private static native void fclose(long f);
}
JNIEXPORT jlong JNICALL Java_com_demo_FILE_fopen(JNIEnv *env, jclass cls, jstring fname, jstring fmode)
{
   char *szfname = (*env)->GetStringUTFChars(env, fname, 0);
   char *szmode = (*env)->GetStringUTFChars(env, fmode, 0);
   FILE* f = fopen(szfname, szmode);
   (*env)->ReleaseStringUTFChars(env, fmode, szmode);
   (*env)->ReleaseStringUTFChars(env, fname, szname);
   retrun (jlong)(f);
}

JNIEXPORT jlong JNICALL Java_com_demo_FILE_fputs(JNIEnv *env, jclass cls, jlong jf, jstring s)
{
   char *szs = (*env)->GetStringUTFChars(env, s, 0);
   FILE* f = reinterpret_cast<FILE*>(jf);
   long len = fputs(f, szs);
   (*env)->ReleaseStringUTFChars(env, s, szs);
   retrun len;
}

JNIEXPORT void JNICALL Java_com_demo_FILE_fclose(JNIEnv *env, jclass cls, jlong jf)
{
   FILE* f = reinterpret_cast<FILE*>(jf);
   fclose(f);
}