Pregunta

I am currently developing an Android application which uses a native C library. I am very unfamiliar with C, and am having some conversion problems. I know that the problem has something to do with signed/unsigned numbers, but cannot figure out what I need to do to fix this.

The C library works fine on its own, and produces the correct results. However when I port it back to Android, only the positive values are correct. The negative values are returned as 256 minus the value.

For example:

 8 -> 8
 5 -> 5
 1 -> 1
 0 -> 0
-3 -> 253
-5 -> 251
-8 -> 248

This is what the C code looks like when it assigns the value:

BYTE *parms;
WORD __stdcall GetValue(BYTE what, long *val){

    char myStringParmsOne[255];
    sprintf( myStringParmsOne, "parms[1]=%d", parms[1] );
    LOG_INFO( myStringParmsOne );

    char myStringIsG[255];
    sprintf( myStringIsG, "API_isG=%d",API_isG );
    LOG_INFO( myStringIsG );

    char myStringCharParmsB[255];
    sprintf( myStringCharParmsB, "(char)parms[1]=%d", (char)parms[1] );
    LOG_INFO( myStringCharParmsB );

    *val=(char)parms[1]-(API_isG?11:0);
}

The LOG_INFO statements print the values to LogCat. Below I have values when the program is run and a value of -3 is expected.

The first **parms[1]=%d** statement returns **parms[1]=253**

The second **API_isG=%d** statement returns **API_isG=0**

The third **(char)parms[1]=%d** statement returns **(char)parms[1]=253**

The BYTE and WORD types are defined as follows:

typedef unsigned char BYTE;
typedef unsigned short WORD;

The wrapper function I use to send this value back to Java is shown below:

long Java_my_package_Model_00024NativeCalls_GetValueJava( JNIEnv *env, jobject obj, WORD what) {
    long c;
    int j = GetValue( what, &c );
    if( j == 0 ) {
        return c;
    } else {
        return -1;
    }
}

EDIT

The GetValue method is used all the time, but only this individual call gives me problems with negative numbers, it works with other calls. I have tried the two following things for my wrapper function:

long Java_my_package_Model_00024NativeCalls_GetValueJava( JNIEnv *env, jobject obj, WORD what) {
    long c;
    int j = GetValue( what, &c );
    if( j == 0 ) {
        return (signed char)c;
    } else {
        return -1;
    }
}

The casting of the return value above provides me with a proper return value. However, all of the other calls to this function for other values are completely haywire.

long Java_my_package_Model_00024NativeCalls_GetValueJava( JNIEnv *env, jobject obj, WORD what) {
    long c;
    int j = GetValue( what, &c );
    if( j == 0 ) {
        return (signed long)c;
    } else {
        return -1;
    }
}

The above casting of the return value changed nothing.

¿Fue útil?

Solución

This happens because you are putting an unsigned char (IIRC in NDK char is unsigned by default) inside a long. If the value you put inside the long was signed then the compiler would have changed also the sign bit of the long.

Try to change the cast from

*val=(char)parms[1]-(API_isG?11:0);

to

*val=(long)((signed char)parms[1]-(API_isG?11:0));

(not sure if the (long) cast is required, maybe the cast to (signed char) is enough.

Otros consejos

Change the types from unsigned char/unsigned short to char/short if you want to store signed values.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top