Question

hi i have an c function

int main(int argc, char *argv[])

and my wrapper.c has this function

JNIEXPORT jint JNICALL Java_package_Class_lameMain(JNIEnv *env, jclass class, jint argc, jcharArray argv) {
    return main(argc, argv);
}

and in java i've defined it like this

private native int lameMain(int argc, char[] argv);

but i think i'm doing something wrong with the argv-argument... it's not an char-array, but a array of char-pointers.

can anyone help?

when i run it my app crashes with

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

Solution

On the Java side, convert the array to an array of strings (i. e. String[]). Pass it like that. On the JNI side, go through the array and retrieve the characters of each string. The declarations would go like this:

private native int lameMain(String[] argv);

And in C:

JNIEXPORT jint JNICALL Java_package_Class_lameMain(JNIEnv *env, jclass class,  jobjectArray argv )

There's no need to pass argc, because Java arrays store their own size.

That said, you're probably doing something very wrong. Typical Android programs don't start with main and don't take command line arguments - they have activities instead. A C main() function is a starting point of a program, but since you're calling it from the Java side, it's not the first thing in the program.

EDIT: Okay, but I still think you're doing this wrong on more than one count. I take it, the encoder takes a file - right? So you save the wave from memory into a file just to be read again? That's lame (pun intended).

Also, do you really need to pass an arbitrary sized array from the Java side? If you know the number of arguments at design time, and it's small (say, two), it's much, much easier to just pass two jstrings.

Anyway, here goes the array stuff. This assumes the sources of your JNI library are C++, not C. For C, the invokation of JNI functions would be slightly different, and you'd have to use malloc/free instead of new/delete.

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;   
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top