pointer error with c++ and ndk - android

im attempting to build c++ code with ndk-build but i keep getting this error base operand of '->' has non-pointer type 'JNIEnv <aka _JNIEnv>'
i have tried every solution on the first 2 pages of google with no luck, the ndk just isnt being good to me.
nativemain.h
#ifndef NATIVEMAIN_H
#define NATIVEMAIN_H
#include <string.h>
#include <jni.h>
extern "C"
{
JNIEXPORT jstring JNICALL Java_com_ndktest3_MyRenderer_stringFromJNI( JNIEnv* env,
jobject thiz );
}
#endif
nativemain.cpp
#include <nativemain.h>
JNIEXPORT jstring JNICALL Java_com_ndktest3_MyRenderer_stringFromJNI( JNIEnv* env,
jobject thiz )
{
return env->NewStringUTF("Hello from JNI !");
}
Android.mk
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := nativemain
LOCAL_SRC_FILES := nativemain.cpp
include $(BUILD_SHARED_LIBRARY)

Try changing your syntax slightly
I believe the error is the miss-use of the '->' operator
"
{
return env->NewStringUTF("Hello from JNI !");
}
try casting env as a pointer like so
{
return (*env)->NewStringUTF(env, str);
}
where str is a predefined string such as your hello message.
check this post as a cross reference: Do I need to clean up the char* passed to NewStringUTF?

Related

Android NDK / JNI - undefined reference to function defined by using prebuild library

I tried to use a prebuild shared library in JNI.
But when I built JNI library, it always complain function undefined reference.
Here is my Android.mk file.
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := mtestlib
LOCAL_SRC_FILES := mtest/arm64-v8a/lib/libtest.so
LOCAL_EXPORT_C_INCLUDES := mtest/arm64-v8a/include
LOCAL_EXPORT_LDLIBS := mtest/arm64-v8a/lib/libtest.so
LOCAL_PRELINK_MODULE := true
include $(PREBUILT_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := myJNI
LOCAL_SRC_FILES := myJNI.cpp
LOCAL_C_INCLUDES := $(LOCAL_PATH)/mtest/arm64-v8a/include
LOCAL_SHARED_LIBRARY := mtestlib
include $(BUILD_SHARED_LIBRARY)
This is my JNI file.
#include "lucien_example_com_jtest_myNDK.h"
#include <android/log.h>
#include <iostream>
#include <iostream>
#include "Mtest.h"
JNIEXPORT jint JNICALL Java_lucien_example_com_jtest_myNDK_test
(JNIEnv *env, jobject, jstring tmp){
const char* str;
str = env->GetStringUTFChars(tmp,false);
std::cout<< str << std::endl;
env->ReleaseStringUTFChars(tmp,str);
mtest(str);
}
Mtest.h Header:
#include <stdio.h>
#include <stdlib.h>
#include <cutils/properties.h>
#include <utils/Log.h>
int mtest(const char *str);
mtest source file:
#include "Mtest.h"
#define LOG_TAG "Test"
int mtest(const char *str){
ALOGE("[Lucien] test(%s)", str);
return 0;
}
I don't know why I got complain undefined reference when JNI load mtest() function.
The header and prebuild lib are already included.
Which wrong step causes this error?
Please help me, thanks.
The name of your function are not the same in .h file and source file:
int mtest(const char *str);
int mjpeg(const char *str){
ALOGE("[Lucien] test(%s)", str);
return 0;
}
try calling mtest in your source file:
int mtest(const char *str){
ALOGE("[Lucien] test(%s)", str);
return 0;
}
To match with your jni call:
JNIEXPORT jint JNICALL Java_lucien_example_com_jtest_myNDK_test
(JNIEnv *env, jobject, jstring tmp){
...
mtest(str);
}
EDIT 1
Your jni function expect to return a jint but you aren't returning anything. Try with a return statement at the end of the function:
JNIEXPORT jint JNICALL Java_lucien_example_com_jtest_myNDK_test
(JNIEnv *env, jobject, jstring tmp){
const char* str;
str = env->GetStringUTFChars(tmp,false);
std::cout<< str << std::endl;
env->ReleaseStringUTFChars(tmp,str);
mtest(str);
//Example:
return 0;
}

Passing arguments to JNI giving error java.lang.UnsatisfiedLinkError

I just started to use NDK and i ran Hello_Jni and i know how that works but i wanted to try do something like this and cant get it to work (Im doing this manually)
simple.c
#include "simple.h"
#include <jni.h>
JNIEXPORT jdouble JNICALL
Java_com_example_Test_round_decimals (JNIEnv * env, jobject obj, jdouble value, jint decimals) {
double m = pow (10, decimals);
return (double) round (value * m) / m;
}
JNIEXPORT jstring JNICALL Java_com_example_Test_hello(JNIEnv* env, jobject javaThis) {
return (*env)->NewStringUTF(env, "Hello from ME!");
}
simple.h
#include <stdio.h>
#include <stdlib.h>
#include "math.h"
#include <string.h>
#include <jni.h>
JNIEXPORT jdouble JNICALL Java_com_example_Test_round_decimals (JNIEnv * env, jobject obj,jdouble value, jint decimals);
JNIEXPORT jstring JNICALL Java_com_example_Test_hello(JNIEnv* env, jobject javaThis);
Activity
public class Test{
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
double test = round_decimals(10.1234,2);
double test2 = hello();
Log.i("Round","Number" + test); // i would like to get this
Log.i("String","hello? " + test2); // this works it shows "Hello From ME!"
}
public native double round_decimals(double value, int decimals);
public native String hello();
static {
System.loadLibrary("simple");
}
}
Android.mk
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := simple
LOCAL_SRC_FILES := simple.c
LOCAL_C_INCLUDES := $(LOCAL_PATH)
include $(BUILD_SHARED_LIBRARY)
android.mk, simple.c and simple.h are in JNI folder of my Activity.
And also running Build-ndk in folder of my Activity shows no errors
But when i try to build it on my tablet i get this error.
java.lang.UnsatisfiedLinkError:round_decimals
You generated the .h file from a version of the .java that had a package statement in it, then you modified the .java file to remove the package statement, then you compiled and ran, and nothing matched up.
There's something else wrong here. The method signature should be (JNIEnv*, jobject, jdouble, jint) if you've generated the files correctly.
Regenerate the .h file and adjust the .c file accordingly.
i Found the problem it was with Java_com_example_Test_round_decimals had to rename it to
Java_com_example_Test_roundDecimals and with that i had to rename public native double round_decimals(double value, int decimals); to public native double roundDecimals(double value, int decimals);
You had an underscore (_) inside your method name and underscores are name delimiters in JNI convention.
Changing the java method name to camel case is a solution but you can also escape underscores using _1 in your native method name, like so: Java_com_example_Test_round_1decimals.

Link FFMpeg in Android

I want to use FFMpeg on android. I'm really new to this topic. I build libraries with this tutorial]1. Now I have .so and .h files but I dont know how to use them in my project. I probably need to link it in my Android.mk file. Here is my .mk and .c file in my project:
Android.mk
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_LDLIBS := -llog
LOCAL_MODULE := ndksetup
LOCAL_SRC_FILES := native.c
include $(BUILD_SHARED_LIBRARY)
native.c
#include <jni.h>
#include <string.h>
#include <android/log.h>
#define DEBUG_TAG "NDKSetupActivity"
void Java_com_example_ndksetup_MainActivity_printLog(JNIEnv *env, jobject this, jstring logString)
{
jboolean isCopy;
const char * szLogString = (*env)->GetStringUTFChars(env, logString, &isCopy);
__android_log_print(ANDROID_LOG_DEBUG, DEBUG_TAG, "NDK: %s", szLogString);
(*env)->ReleaseStringUTFChars(env, logString, szLogString);
}
jint Java_com_example_ndksetup_MainActivity_fibonacci(JNIEnv * env, jobject this, jint value)
{
if (value <= 1) return value;
return Java_com_example_ndksetup_MainActivity_fibonacci(env, this, value-1)
+ Java_com_example_ndksetup_MainActivity_fibonacci(env, this, value-2);
}
Can anyone tell me how I can use .so and .h files in my native.c file?
This how you would make calls to lib files in your JNI folder from your native C file
JNIEXPORT jstring JNICALL Java_*(JNIEnv *pEnv, jobject pObj) {
char* lCodecName = gVideoCodecCtx->codec->name;
return (*pEnv)->NewStringUTF(pEnv, lCodecName);
}
and this is how you link the native libraries from your Java code
static {
System.loadLibrary("<native jni lib file name>");
}

UnsatisfiedLinkError when calling C++ method in C++ file from Java file

It looks like it is the popular problem,
And I still not find out the solution.
package name : app.cloudstringers
Java file : Completed.java
static {
try {
System.loadLibrary("ffmpeg");
} catch (UnsatisfiedLinkError e) {
Log.d("", "Error : " + e.toString());
}
}
// Define native method
public native int getString();
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.page_completed);
// Call native method
Log.d("", "" + getString());
C++ file : ffmpeg.cpp
#include <jni.h>
#include <android/log.h>
#include <string.h>
#ifdef __cplusplus
extern "C" {
#endif
JNIEXPORT jstring JNICALL Java_app_cloudstringers_Completed_getString(JNIEnv* env, jobject thiz)
{
jstring strRet = env->NewStringUTF("HelloWorld from JNI !");
return strRet;
}
#ifdef __cplusplus
}
#endif
Android.mk file
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := ffmpeg
LOCAL_SRC_FILES := ffmpeg.cpp
include $(BUILD_SHARED_LIBRARY)
I run application but still get the error exception UnsatisfiedLinkError : getString
People who know the how to fix this problem,
Please tell me,
Thanks
UPDATE
Follow #dextor answer. Sorry because I get the mistake. Only thing I need for this question is change from public native int getString() to public native String getString().
It works now.
Not sure (didn't actually try), but the only wrong thing I've noticed is the return type of your method declarations.
Java-side
public native int getString()
NDK-side
JNIEXPORT jstring JNICALL Java_app_cloudstringers_Completed_getString(JNIEnv* env, jobject thiz)
In Java, you have an int. On the C-side, you have a jstring.

android ndk (opencv)

I got a crash when i call my native functions in my android application here is my code :
lib libo=new lib();
public void onPreviewFrame(byte[] data, Camera camera)
{
int s;// where w and h are width and height are the parameters of the camera
s=libo.getdata(data);/: and getdata is my native function
}
my getdata.c :
#include "getdata.h"
JNIEXPORT int JNICALL JAVA_android_video8_libo_som
(JNIEnv* env, jobject obj,jbyte* data)
{
return (data[1]);
}
getdata.h :
#include <jni.h>
#ifndef _Included_android_video8_lib
#define _Included_android_video8_lib
#ifdef __cplusplus
extern "C" {
#endif
JNIEXPORT int JNICALL JAVA_android_video8_libo_som(JNIEnv* env, jobject obj, jbyte*);
#ifdef __cplusplus
}
#endif
#endif
Android.mk :
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := opcv
LOCAL_SRC_FILES := getdata.c
include $(BUILD_SHARED_LIBRARY)
and the class where i call the lib :
package android.video8;
public class libo {
static {
System.loadLibrary("opcv");
}
public native static int som(int s);
}
the library is generated without a problem but the exécution of the apps give me a crash
i don't no where ehe error is
thanks
Seems there're some errors in your question. Anyway, you're using wrong prototypes for JNI functions. You should use these signatures:
JNIEXPORT
jint JNICALL JAVA_android_video8_libo_getData(JNIEnv*, jclass, jbyteArray);
JNIEXPORT
jint JNICALL JAVA_android_video8_libo_som(JNIEnv*, jclass, jint);
And use javah tool every time you change native method's prototype.

Categories

Resources