Search code examples
javaandroidcandroid-ndkjava-native-interface

android NDK function returning wrong values for 64bits variables (double, long int)


I'm trying to cope with android NDK in android studio, I set up a demo app with a jni folder with the required files, it seems to work as expected when I call a function that returns an int or a const char*, but when it comes to doubles it just doesn't behave.
I tried to cast the returned value to jdouble, and also tried to declare the functions as returning a long double with same results. The app is running on a nexus 5 and I have no idea what's wrong.
As requested, here a few try, on the left the return statement in c, on the right the value got in java
return 0 -> 0
return 1 -> 0
return 1.555 -> -1.374389535E9
return 10 -> 0
return 10.555 -> -1.71798692E8
return 2000 -> 0
return 2000.123 -> -2.0615843E8
Ok, it seems like integer values are returned as 0...?

EDIT:
I added a new function getMyLong as done with other functions

long int getMyLong(){ return 0x1122334455667788;}

the interesting thing is, if in main.c the bridge function is defined calling the function from func.c it returns just what appears to be a 32bit portion, while if I return the value directly from the bridge function, it works and so it does with doubles

JNIEXPORT jlong JNICALL Java_com_lelloman_jni_1test_MainActivity_getMyLong
    (JNIEnv * env, jobject obj){
          return getMyLong(); // this one will return 1432778632 in java
          //return 0x1122334455667788; this one returns 1234605616436508552 
    }


Edit2:
regarding the build configuration and ndk, I barely know what I'm doing but I'll do my best to point out what I know:
- in local.properties I added this line ndk.dir=/usr/share/android-studio/data/ndk
- in ndk/RELEASE.TXT says r10c (64-bit) - in build.gradle I added this inside defaultConfig (I also tried without cFlags, it's the same)

ndk {
    moduleName "ndkTest"
    cFlags "-std=c99"
}

- javah generated a file named com_lelloman_jni_test_MainActivity.h, the only include there is #include <jni.h> - I wrote main.c and the only include is the file generated with javah

main.c

#include "com_lelloman_jni_test_MainActivity.h"

JNIEXPORT jint JNICALL Java_com_lelloman_jni_1test_MainActivity_getMyInt
  (JNIEnv * env, jobject obj, jint b, jint h){
        return getMyInt( b, h);
  }    
JNIEXPORT jdouble JNICALL Java_com_lelloman_jni_1test_MainActivity_getMyDouble
  (JNIEnv *env, jobject obj, jdouble r){
        return getMyDouble(r);
  } 

func.h

#ifndef FUNC_H_INCLUDED
#define FUNC_H_INCLUDED


int getMyInt(int b,int h);
double getMyDouble(double r);
const char* getMyString(int q);

#endif // FUNC_H_INCLUDED

func.c

#include "func.h"

#ifndef PI
#define PI 3.14159265359
#endif // PI


int getMyInt(int b,int h){
    return b*h;
}

double getMyDouble(double r){
    //return r*PI*2;
    //return 5;
    return 1*2.23;
}    

Solution

  • Main.c should include func.h, or else main.c thinks getMyDouble() returns an int.