Android ndk 如何使用JNI调用;“主要”;接受字符指针数组的函数?

Android ndk 如何使用JNI调用;“主要”;接受字符指针数组的函数?,android-ndk,java-native-interface,main,Android Ndk,Java Native Interface,Main,嗨,我有一个c函数 int main(int argc, char *argv[]) 我的wrapper.c有这个函数 JNIEXPORT jint JNICALL Java_package_Class_lameMain(JNIEnv *env, jclass class, jint argc, jcharArray argv) { return main(argc, argv); } 在java中,我这样定义它 private native int lameMain(int arg

嗨,我有一个c函数

int main(int argc, char *argv[])
我的wrapper.c有这个函数

JNIEXPORT jint JNICALL Java_package_Class_lameMain(JNIEnv *env, jclass class, jint argc, jcharArray argv) {
    return main(argc, argv);
}
在java中,我这样定义它

private native int lameMain(int argc, char[] argv);
但我认为我在argv的论点上做错了什么。。。它不是一个字符数组,而是一个字符指针数组

有人能帮忙吗

当我运行它时,我的应用程序会崩溃

03-20 23:26:23.487: A/libc(30436): Fatal signal 11 (SIGSEGV) at 0xfd90001d (code=1), thread 30436 (package)

在Java端,将数组转换为字符串数组(即
String[]
)。像那样传过去。在JNI端,遍历数组并检索每个字符串的字符。声明如下:

private native int lameMain(String[] argv);
在C中:

JNIEXPORT jint JNICALL Java_package_Class_lameMain(JNIEnv *env, jclass class,  jobjectArray argv )
不需要传递argc,因为Java数组存储自己的大小

也就是说,你可能做错了什么。典型的Android程序不以
main
开头,也不接受命令行参数,而是有活动。C
main()
函数是程序的起点,但由于您是从Java端调用它,因此它不是程序中的第一件事

编辑:好吧,但我仍然认为你在不止一个方面做错了。我拿走了,编码器拿走了一个文件-对吗?所以你把wave从内存保存到一个文件中,以便再次读取?那是蹩脚的(双关语)

另外,您真的需要从Java端传递任意大小的数组吗?如果您知道设计时的参数数量,并且参数数量很小(比如说,两个),那么只需传递两个
jstring
s就非常容易了

不管怎样,这里是数组的东西。这假设JNI库的源是C++,而不是C。对于C,JNI函数的调用会略有不同,并且您必须使用MalC/C++/NeX/DELATION。
JNIEXPORT jint JNICALL Java_package_Class_lameMain(JNIEnv *env, jclass class,  jobjectArray jargv)
{    //jargv is a Java array of Java strings
    int argc = env->GetArrayLength(jargv);
    typedef char *pchar;
    pchar *argv = new pchar[argc];
    int i;
    for(i=0; i<argc; i++)
    {
        jstring js = env->GetObjectArrayElement(jargv, i); //A Java string
        const char *pjc = env->GetStringUTFChars(js); //A pointer to a Java-managed char buffer
        size_t jslen = strlen(pjc);
        argv[i] = new char[jslen+1]; //Extra char for the terminating null
        strcpy(argv[i], pjc); //Copy to *our* buffer. We could omit that, but IMHO this is cleaner. Also, const correctness.
        env->ReleaseStringUTFChars(js, pjc);
    }

    //Call main
    main(argc, argv);

    //Now free the array
    for(i=0;i<argc;i++)
        delete [] argv[i];
    delete [] argv;   
}
JNIEXPORT jint JNICALL Java_package_Class_lameMain(JNIEnv*env,jclass类,jobjectArray jargv)
{//jargv是Java字符串的Java数组
int argc=env->GetArrayLength(jargv);
typedef char*pchar;
pchar*argv=新的pchar[argc];
int i;
for(i=0;iGetObjectArrayElement(jargv,i);//一个Java字符串
const char*pjc=env->GetStringUTFChars(js);//指向Java托管字符缓冲区的指针
尺寸jslen=strlen(pjc);
argv[i]=新字符[jslen+1];//终止null的额外字符
strcpy(argv[i],pjc);//复制到*our*缓冲区。我们可以忽略它,但这更干净。还有,常量正确性。
环境->发布StringUTFChars(js,pjc);
}
//呼叫总管
主(argc、argv);
//现在释放数组

对于Java端的(i=0;i,将数组转换为字符串数组(即
String[]
)。这样传递它。在JNI端,遍历数组并检索每个字符串的字符。声明如下:

private native int lameMain(String[] argv);
在C中:

JNIEXPORT jint JNICALL Java_package_Class_lameMain(JNIEnv *env, jclass class,  jobjectArray argv )
不需要传递argc,因为Java数组存储自己的大小

也就是说,您可能做了一些非常错误的事情。典型的Android程序不以
main
开头,也不接受命令行参数——它们有活动。C
main()
函数是程序的起点,但由于您是从Java端调用它,因此它不是程序中的第一件事

编辑:好的,但我仍然认为你在不止一个方面犯了错误。我认为,编码器接收了一个文件-对吗?所以你将波形从内存保存到一个文件中,只是为了再次读取?这是蹩脚的(双关语)

另外,您真的需要从Java端传递任意大小的数组吗?如果您在设计时知道参数的数量,并且参数很小(比如说,两个),那么只传递两个
jstring
s就非常容易了

无论如何,这里的数组内容。假设你的JNI库的源是C++,而不是C。对于C,JNI函数的调用会稍微不同,并且你必须使用MalC/C,而不是NeX/Delphi。

JNIEXPORT jint JNICALL Java_package_Class_lameMain(JNIEnv *env, jclass class,  jobjectArray jargv)
{    //jargv is a Java array of Java strings
    int argc = env->GetArrayLength(jargv);
    typedef char *pchar;
    pchar *argv = new pchar[argc];
    int i;
    for(i=0; i<argc; i++)
    {
        jstring js = env->GetObjectArrayElement(jargv, i); //A Java string
        const char *pjc = env->GetStringUTFChars(js); //A pointer to a Java-managed char buffer
        size_t jslen = strlen(pjc);
        argv[i] = new char[jslen+1]; //Extra char for the terminating null
        strcpy(argv[i], pjc); //Copy to *our* buffer. We could omit that, but IMHO this is cleaner. Also, const correctness.
        env->ReleaseStringUTFChars(js, pjc);
    }

    //Call main
    main(argc, argv);

    //Now free the array
    for(i=0;i<argc;i++)
        delete [] argv[i];
    delete [] argv;   
}
JNIEXPORT jint JNICALL Java_package_Class_lameMain(JNIEnv*env,jclass类,jobjectArray jargv)
{//jargv是Java字符串的Java数组
int argc=env->GetArrayLength(jargv);
typedef char*pchar;
pchar*argv=新的pchar[argc];
int i;
for(i=0;iGetObjectArrayElement(jargv,i);//一个Java字符串
const char*pjc=env->GetStringUTFChars(js);//指向Java托管字符缓冲区的指针
尺寸jslen=strlen(pjc);
argv[i]=新字符[jslen+1];//终止null的额外字符
strcpy(argv[i],pjc);//复制到*our*缓冲区。我们可以忽略它,但这更干净。还有,常量正确性。
环境->发布StringUTFChars(js,pjc);
}
//呼叫总管
主(argc、argv);
//现在释放数组

对于(i=0;ihi谢谢..我会尝试一下,我想调用lame编码器前端的主函数,以避免编写我自己的wave解析器等..如果我在wrapper.c中硬编码argv数组似乎是可行的,但直到现在还不能作为java参数…我会尝试更详细地解释如何将jobjectArray转换为“char*argv[]”?
GetStringUTFChars
适用于许多字符,但通常C函数不喜欢修改的UTF-8编码字符串。调用
GetBytes()
GetBytes(“UTF-8”)
java.lang.String
实例上,然后复制到缓冲区并NUL终止它。但是,如果您要使用修改的UTF,
GetStringLength
不是
GetStringUTFChars
所需的字节数。请改用
GetStringUTFLength
。注意;修复了。无论如何,OP可能做错了。我是一个回答这个问题,但我觉得OP的任务可以更容易地完成。嗨,谢谢。我会尝试一下,我想调用lame编码器前端的主要功能,以避免编写我自己的wave解析器等。如果我在wrapper.c中硬编码argv数组,这似乎是可行的,但直到现在还不能作为java参数……我可以试着向您详细解释一下我是如何做到这一点的吗将jobjectArray转换为“char*argv[]”?
GetStringUTFChars
将适用于许多字符