Android JNI ndk-build error: 'jni' has not been declared - android

I want to use dynamic registration in native method, so I need set JNI_onLoad function. I just write a function to get sum of two numbers. But, it can't build correctly. How can I correct the error?
This is my *.cpp file, I name this file jni.cpp
#include <jni.h>
extern "C" JNIEXPORT jint JNI_OnLoad(JavaVM *vm, void *reserved) {
jni::JNIEnv& env = jni::GetEnv(*vm, jni::jni_version_1_6);
jni::jclass& nativeClass = jni::FindClass(env, "com/test/NativeClass");
#define MAKE_NATIVE_METHOD(name, sig) jni::MakeNativeMethod<decltype(name), name>( #name, sig )
jni::RegisterNatives(env, nativeClass, MAKE_NATIVE_METHOD(nativeAddTest, "(II)I") );
return JNI_VERSION_1_6;
}
jlong nativeAddTest(JNIEnv *env, jni::jobject* obj, jni::jint a, jni::jint b) {
return a+b;
}
Android.mk
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := test
LOCAL_SRC_FILES := jni.cpp
LOCAL_LDLIBS := -L/ndk-path/sources/cxx-stl/stlport/libs/armeabi
include $(BUILD_SHARED_LIBRARY)
When I use ndk-build command, it's wrong. But I really dont't konw the reason...
D:\WorkSpaces\Test\app\src\main\jni>ndk-build
[x86] Compile++ : test <= jni.cpp
D:/WorkSpaces/Test/app/src/main/jni/jni.cpp: In function 'jint JNI_OnLoad(JavaVM*, void*)':
D:/WorkSpaces/Test/app/src/main/jni/jni.cpp:9:5: error: 'jni' has not been declared
jni::JNIEnv& env = jni::GetEnv(*vm, jni::jni_version_1_6);
^
D:/WorkSpaces/Test/app/src/main/jni/jni.cpp:9:18: error: 'env' was not declared in this scope
jni::JNIEnv& env = jni::GetEnv(*vm, jni::jni_version_1_6);
....
It seems can't find jni.h, but I already have #include<jni.h>

In Android NDK, <jni.h> does not define a jni namespace. Simply remove all jni::
#include <jni.h>
extern "C" JNIEXPORT jint JNI_OnLoad(JavaVM *vm, void *reserved) {
JNIEnv env;
vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6);
jclass nativeClass = env->FindClass("com/test/NativeClass");
… and so on.

Add header location to your android.mk
LOCAL_C_INCLUDES := "path to your header location"

Related

Create a C++ class and Use that class In Another C++ Class Which contain JNI methods in ndk android

In Android, I am facing issues in connecting two cpp class in native Android. I have tested with the single class it working fine.
but when I have created another file and now facing an issue in linking it with current cpp file.
MainClass.cpp
#include <jni.h>
#include "native-handler.h"
extern "C"
JNIEXPORT jstring JNICALL
Java_com_example_fragment_SampleFragment_setTitle(JNIEnv *env,jobject instance,jobject context) {
ClassNativeHandler classNativeHandler;
return classNativeHandler.getType(env,context);
}
native-handler.cpp
#include <jni.h>
#include "native-handler.h"
jstring jstringObject;
jstring ClassNativeHandler::getType(JNIEnv *env, jobject contextObject) {
jstring jstringObject = env->NewStringUTF("Hello world");
return jstringObject;
}
void ClassNativeHandler::setType(jstring string) {
myType = string;
jstringObject = string;
}
native-handler.h
#ifndef SAMPLE_NATIVE_HANDLER_H
#define SAMPLE_NATIVE_HANDLER_H
#include <iostream>
#include <string>
class ClassNativeHandler
{
private:
jstring myType;
public:
void setType(jstring string);
jstring getType(JNIEnv *env, jobject contextObject);
jstring getHeaderName(JNIEnv *env);
};
#endif //SAMPLE_NATIVE_HANDLER_H
Android.mk
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := Native
LOCAL_SRC_FILES := ../cpp/mainClass.cpp
LOCAL_C_INCLUDES := ../cpp/native-handler.h
LOCAL_LDLIBS := -lz -llog -ljnigraphics
include $(BUILD_SHARED_LIBRARY)
Error : undefined reference to `ClassNativeHandler::getType(_JNIEnv*, _jobject*)'
on this line
return classNativeHandler.getType(env,context);
So I am not able to build the .so file. Please guide me
You haven't compiled native-handler.cpp. You need to specify it in LOCAL_SRC_FILES so that NDK compiles it.
LOCAL_SRC_FILES := ../cpp/mainClass.cpp ../cpp/native-handler.cpp

ndk-build error: no such file or directory

I have made a project with OpenCV and i need to use Native Code for realtime processing purpose, following the guide on this book opencv3, here is my Android.mk file:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := FinalCamJNI
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
LOCAL_LDLIBS := -lstdc++ # C++ standard library
LOCAL_LDLIBS += -llog # Android logging
LOCAL_LDLIBS += -lz # zlib
LOCAL_STATIC_LIBRARIES := opencv_calib3d
LOCAL_STATIC_LIBRARIES += opencv_features2d
LOCAL_STATIC_LIBRARIES += opencv_flann
LOCAL_STATIC_LIBRARIES += opencv_imgproc
LOCAL_STATIC_LIBRARIES += opencv_core
LOCAL_SRC_FILES := FinalCamJNI.cpp RecolorRCFilter.cpp
include $(BUILD_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := opencv_calib3d
LOCAL_SRC_FILES := libs/$(TARGET_ARCH_ABI)/libopencv_calib3d.a
include $(PREBUILT_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := opencv_features2d
LOCAL_SRC_FILES := libs/$(TARGET_ARCH_ABI)/libopencv_features2d.a
include $(PREBUILT_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := opencv_flann
LOCAL_SRC_FILES := libs/$(TARGET_ARCH_ABI)/libopencv_flann.a
include $(PREBUILT_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := opencv_imgproc
LOCAL_SRC_FILES := libs/$(TARGET_ARCH_ABI)/libopencv_imgproc.a
include $(PREBUILT_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := opencv_core
LOCAL_SRC_FILES := libs/$(TARGET_ARCH_ABI)/libopencv_core.a
include $(PREBUILT_STATIC_LIBRARY)
and here is my Application.mk file:
APP_STL := gnustl_static # GNU STL
APP_CPPFLAGS := -frtti –fexceptions # RTTI, exceptions
APP_ABI := armeabi armeabi-v7a mips x86
APP_PLATFORM := android-8
I'm facing this error when performing ndk-build:
I have checked the directory, and ensured that i have prepared all the code file
in jni folder.
In addition, here is my implementation file:
FinalCamJNI.cpp:
#include <jni.h>
#include "RecolorRCFilter.hpp"
using namespace finalcam;
#ifdef __cplusplus
extern "C" {
#endif
JNIEXPORT jlong JNICALL
Java_nahuy_hcmus_finalcam_filters_newSelf(
JNIEnv *env, jclass clazz)
{
RecolorRCFilter *self = new RecolorRCFilter();
return (jlong)self;
}
JNIEXPORT void JNICALL
Java_nahuy_hcmus_finalcam_filters_deleteSelf(
JNIEnv *env, jclass clazz, jlong selfAddr)
{
if (selfAddr != 0)
{
RecolorRCFilter *self = (RecolorRCFilter *)selfAddr;
delete self;
}
}
JNIEXPORT void JNICALL
Java_nahuy_hcmus_finalcam_filters_apply(
JNIEnv *env, jclass clazz, jlong selfAddr, jlong srcAddr,jlong dstAddr)
{
if (selfAddr != 0)
{
RecolorRCFilter *self = (RecolorRCFilter *)selfAddr;
cv::Mat &src = *(cv::Mat *)srcAddr;
cv::Mat &dst = *(cv::Mat *)dstAddr;
self->apply(src, dst);
}
}
#ifdef __cplusplus
} // extern "C"
#endif
RecolorRCFilter.hpp:
#ifndef RECOLOR_RC_FILTER
#define RECOLOR_RC_FILTER
#include <opencv2/core/core.hpp>
namespace finalcam {
class RecolorRCFilter
{
public: // All subsequent methods or variables are public.
void apply(cv::Mat &src, cv::Mat &dst);
private: // All subsequent methods or variables are private.
cv::Mat mChannels[4];
};
} // namespace secondsight
#endif // RECOLOR_RC_FILTER
RecolorRCFilter.cpp:
#include "RecolorRCFilter.hpp"
using namespace finalcam;
void RecolorRCFilter::apply(cv::Mat &src, cv::Mat &dst)
{
cv::split(src, mChannels);
cv::Mat g = mChannels[1];
cv::Mat b = mChannels[2];
// dst.g = 0.5 * src.g + 0.5 * src.b
cv::addWeighted(g, 0.5, b, 0.5, 0.0, g);
// dst.b = dst.g
g.copyTo(b);
cv::merge(mChannels, 4, dst);
}
Can anyone explain me why this happens and what I can do to solve this problem?

CPP undefined reference to function in same file

While compiling a CPP project into an .so library it generates the following errors :
...
jni/core/src/sqlite3/sqlite3c++.h:26: error: undefined reference to 'sqlite3cpp::database::mp_checkSqliteError(int, std::string)'
jni/core/src/sqlite3/sqlite3c++.h:51: error: undefined reference to 'sqlite3cpp::query::compile()'
jni/core/src/sqlite3/sqlite3c++.h:51: error: undefined reference to 'sqlite3cpp::database::mp_checkSqliteError(int, std::string)'
jni/core/src/sqlite3/sqlite3c++.h:53: error: undefined reference to 'sqlite3cpp::query::compile()'
...
Where those files are :
part of sqlite3c++.h :
.....
#include "sqlite3.h"
#ifndef MFDEPSAPI
#define MFDEPSAPI
#endif
namespace sqlite3cpp
{
class MFDEPSAPI database
{
public:
database(std::string databaseFile): mp_transactionInProgress(false), mp_SQLITE_db(0) { if(databaseFile.empty()) return; mp_checkSqliteError(sqlite3_open_v2(databaseFile.c_str(), &mp_SQLITE_db, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_FULLMUTEX, 0), "opening database"); }
~database();
....
class MFDEPSAPI query
{
public:
query(database& db, const char* strQuery);
~query();
void compile();
....
}
}
part of sqlite3c++.cpp :
#include "sqlite3.h"
#include "sqlite3c++.h"
#include <iostream>
using namespace std;
namespace sqlite3cpp
{
....
int database::mp_checkSqliteError(int retVal, const std::string description)
{
switch(retVal)
{
case -1:
cerr << "non-typed sqlite library error: " << description << "\n";
return retVal;
break;
case SQLITE_ERROR:
case SQLITE_MISUSE:
case SQLITE_FULL:
case SQLITE_NOMEM:
case SQLITE_INTERRUPT:
case SQLITE_INTERNAL:
case SQLITE_PERM:
case SQLITE_CORRUPT:
case SQLITE_CANTOPEN:
case SQLITE_AUTH:
case SQLITE_RANGE:
case SQLITE_NOTADB:
cerr << "sqlite error: (" << retVal << ") " << sqlite3_errmsg(mp_SQLITE_db) << ", description: \"" << description << "\"" << "\n";
return retVal;
break;
default:
return retVal;
};
}
.....
query::query( database& db, const char* strQuery ) : mp_db(db), mp_isValid(false), mp_strQuery(strQuery), mp_currentIndex(0), mp_SQLITE_statement(0)
{
}
}
It's building with cygwin via nkd-build.cmd for android with this Android.mk:
LOCAL_PATH:=$(call my-dir)
include $(CLEAR_VARS)
#### sqlite3
# Here we give our module name and source file(s)
LOCAL_C_INCLUDES := core/src/sqlite3
LOCAL_MODULE := sqlite3
LOCAL_SRC_FILES := core/src/sqlite3/sqlite3.c
include $(BUILD_STATIC_LIBRARY)
#include $(BUILD_SHARED_LIBRARY)
#### Project
include $(CLEAR_VARS)
LOCAL_MODULE := libgame
LOCAL_CFLAGS := -Wall -Wextra
LOCAL_LDLIBS := -llog -lGLESv2
LOCAL_CPP_FEATURES += exceptions
LOCAL_STATIC_LIBRARIES := libsqlite3
LOCAL_SHARED_LIBRARIES := liblog libGLESv2
# To build the whole .so
FILE_LIST := $(wildcard $(LOCAL_PATH)/core/src/*.cpp)
LOCAL_SRC_FILES += $(FILE_LIST:$(LOCAL_PATH)/%=%)
INCLUDE_LIST := $(wildcard $(LOCAL_PATH)/core/src/*.h)
LOCAL_C_INCLUDES += $(INCLUDE_LIST:$(LOCAL_PATH)/%=%)
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)
include $(BUILD_SHARED_LIBRARY)
It's probably just something I missed or got wrong configured.
Feel free to ask if more files or something is needed.

Can't separate header and source files in JNI

in JNI folder:
//File foo.h
#ifndef FOO_H_
#define FOO_H_
class Foo {
public:
Foo();
void Funny();
};
#endif /* FOO_H_ */
//File foo.cpp
#include "foo.h"
cv::string bar[1] = {"FOO"};
Foo::Foo() {
}
void Foo::Funny() {
}
Then, when I call:
Foo foo;
foo.Funny();
ndk-build complains:
error: undefined reference to 'Foo::Foo()
error: undefined reference to 'Foo::Funny()
However, if I put the function implementation in the header file like this:
#ifndef FOO_H_
#define FOO_H_
class Foo {
public:
Foo();
void Funny();
};
Foo::Foo() {
}
void Foo::Funny() {
}
#endif /* FOO_H_ */
The compiler then happily compiles my code.
How could I separate function prototypes and their implementation in JNI?
UPDATE: Here's my Android.mk
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
OPENCV_LIB_TYPE:=STATIC
OPENCV_INSTALL_MODULES:=on
include ../../sdk/native/jni/OpenCV.mk
LOCAL_SRC_FILES := native.cpp
LOCAL_C_INCLUDES += $(LOCAL_PATH)
LOCAL_LDLIBS += -llog -ldl
LOCAL_MODULE := native
include $(BUILD_SHARED_LIBRARY)
The undefined reference is outputted by the linker, not by the Compiler. This means there is no translation unit containing the functions you have used in your code. Telling by the Android.mk file I'd say foo.cpp is missing in your LOCAL_SRC_FILES Statement.

java.lang.UnsatisfiedLinkError: Native method not found

I'm trying to make a NDK application, but I get this error:
java.lang.UnsatisfiedLinkError: Native method not found: com.example.hellondk.jni.HelloNDK.hello:()I
I don't understand because the name of the C++ function is the same as the Java packagename and class
HelloNDK.cpp
#include <jni.h>
JNIEXPORT jint JNICALL Java_com_example_hellondk_jni_HelloNDK_hello(JNIEnv* env, jobject o){
return (jint) 2;
}
HelloNDK.java
package com.example.hellondk.jni;
public class HelloNDK {
public native int hello();
static {
System.loadLibrary("HelloNDK");
}
}
Android.mk
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := HelloNDK
LOCAL_SRC_FILES := HelloNDK.cpp
include $(BUILD_SHARED_LIBRARY)
You're exporting it as a C++ function, but the JNI linker doesn't understand C++ name mangling, so it won't be able to find it.
You can use extern "C" to have the function exported without C++ name mangling:
extern "C" JNIEXPORT jint JNICALL Java_com_example_hellondk_jni_HelloNDK_hello(JNIEnv* env, jobject o)
{
return (jint) 2;
}

Categories

Resources