Android: Error While Generating .so file - android

I'm new to Android and am trying to create a simple SDK+NDK concept. I followed the below steps:
Download NDK
Extract zip file
Create new android project.
Create new folder jni under project.
Define UI as needed.
Create a java file to call all the native methods. Declare all those methods with "native" prefix. Have static block to load library using system.loadLibrary("").
Create corresponding header file using javah -jni filename
Move the generated filename.h file to jni folder.
Write c file that includes the .h file and implements the methods in .h file and saved it.
Create mk file,with following content:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE    :=
LOCAL_SRC_FILES := .c
include $(BUILD_SHARED_LIBRARY)
Go to the project folder in command prompt
Give <ndkfolder>/ndk-build
.so file will be generated
But I got stuck in the "12" point with the following error:
**"Compile thumb : com_cts_c2dmclient_NativeLib <= com_cts_c2dmclient_NativeLib.c
jni/com_cts_c2dmclient_NativeLib.c:3:40: fatal error: com_cts_c2dmclient_NativeL
ib: No such file or directory
compilation terminated.
make: *** [obj/local/armeabi/objs/com_cts_c2dmclient_NativeLib/com_cts_c2dmclien
t_NativeLib.o] Error 1**
Note: The .h file is created successfully.
My com_exampleservice_NativeLib.c file
#include "stdio.h"
#include "malloc.h"
#include <com_exampleservice_NativeLib.h>
JNIEXPORT jint JNICALL Java_com_exampleservice_NativeLib_loop
(JNIEnv * env,jobject obj,jint v1, jint v2){
int loop;
unsigned long int *array;
if(v2 == 0){
array = (unsigned long int *)malloc(v1 * sizeof(unsigned long int));}
else if(v2 == 1)
{
array = realloc(array,sizeof(array)+v1);
}
else{
}
array[0] = 1;
array[1] = 1;
for (loop = 2; loop < v1; loop++) {
array[loop] = array[loop - 1] + array[loop - 2];
}
for (loop = 0; loop < v1; loop++) {
}
if(v2 == 2)
{
free(array);
}
return 0;
}

Your Android.mk file does not look good in your question.
Make sure that the com_exampleservice_NativeLib.h file does exist in your jni directory near your c file.
It may be necessary to add directories to the include path, like
LOCAL_C_INCLUDES += $(LOCAL_PATH)/include
Note that this $(LOCAL_C_INCLUDES) must be a list of absolute paths, not like $(LOCAL_SRC_FILES) which is $(LOCAL_PATH)-based.
Another note is that in your com_exampleservice_NativeLib.c file the use of #include directive ornamenation is not correct. It should go
#include <stdio.h>
#include <malloc.h>
#include "com_exampleservice_NativeLib.h"
See What is the difference between #include <filename> and #include "filename"? for detailed explanation.

I've just been using the NDK for the 1st time as well.
I used SWIG to avoid having to write the Java JNI code manually
I found this tutorial useful:

Related

Calling function from .so file created in android in linux C++ code

I have .so file which I take from apk. With command nm -D libnative-lib.so I took list of functions. I need to call function named Java_com_example_nativelib_utils_Constants_getStringFromJNI . I wrote the code below:
#include <stddef.h>
#include <dlfcn.h>
#include <stdio.h>
int init_library() {
void* hdl = dlopen("./libnative-lib.so", RTLD_LAZY);
if(hdl == 0)
return 0;
else return 1;
}
int main() {
printf("%s\n", (init_library() ? "OK": "ERROR"));
}
and make file:
all: exe
exe: main.c
gcc main.c -fPIC -ldl -o main
but result of program is always "ERROR". I tried libnative-lib.so from x86 and armeabi-v7a architectures (others not present). How to load library and call function from it? C++ or C do not care.
It is not possible to use android .so files in non-android project. similar question is here

Use a shared library with Android NDK

I have a C++ project compiled in a shared library. I need to use that library (.so file) in Android with the NDK.
The idea is that someone else would compile the C++ project and give me the .so file, so that I don't have to compile it on my computer.
I need to reference the .so file in my Android.mk file, and all the solutions I tried did not work. That's where I'm stuck.
So:
is it possible to do what I described without creating one shared library per platform?
how can I reference my .so library in my Android.mk? All the solutions I tried did not work.
To reproduce everything from scratch, I did these steps:
1°) Create a HelloWorld C++ project:
Test.h:
#include <iostream>
class Test {
public:
Test();
~Test();
static std::string getTest();
};
Test.cpp:
#include "Test.h"
std::string Test::getTest()
{
return "Hey!!\n";
}
2°) Create the shared library:
g++ -Wall -shared -fPIC -o libTest.so Test.cpp
This gaves me a libTest.so file, which I can use on a C++ project. Now I want to use it on an Android project.
3°) Create a basic empty Android project:
package: com.so.test
name: CppTest
4°) Create a "Test.java" file next to the MainActivity.java file containing:
package com.so.test;
public class Test {
static {
System.loadLibrary("hellondk");
}
public native String getMessage();
}
5°) Open a terminal and:
cd /path/to/my/android/project/app/src/main/java
javac com/so/test/Test.java
javah com.so.test.Test
This creates the "com_so_test_Test.h" file.
cd /path/to/my/android/project
mkdir jni
mv app/src/main/java/com_so_test_Test.h jni
touch jni/com_so_test_Test.cpp
6°) Add the following code in "com_so_test_Test.cpp" file:
#include <jni.h>
#include <stdio.h>
#include "com_so_test_Test.h"
#include "Test.hpp"
JNIEXPORT jstring JNICALL Java_com_so_test_Test_getMessage(JNIEnv* env, jobject ob)
{
return env->NewStringUTF(Test::getTest().c_str());
}
7°) Copy "Test.h" and "libTest.so" files created on steps 1 & 2 into "jni" folder
8°) Create an "Android.mk" file in the "jni" folder containing:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := hellondk
LOCAL_SRC_FILES := com_so_test_Test.cpp
include $(BUILD_SHARED_LIBRARY)
9°) Create an "Application.mk" file in the "jni" folder containing:
APP_STL := stlport_static
10°) Back in the terminal, run:
/path/to/your/ndk/ndk-build
And that's the step where I'm stuck. I need to reference the libTest.so file in the Android.mk, but all the solutions I tried did not work. Any idea?
EDIT: here is the error I get:
[arm64-v8a] Compile++ : hellondk <= com_so_test_Test.cpp
[arm64-v8a] SharedLibrary : libhellondk.so
./obj/local/arm64-v8a/objs/hellondk/com_so_test_Test.o: In function `Java_com_so_test_Test_getMessage':
/Users/timsandra/Desktop/CppTest/jni/com_so_test_Test.cpp:8: undefined reference to `Test::getTest()'
clang++: error: linker command failed with exit code 1 (use -v to see invocation)
make: *** [obj/local/arm64-v8a/libhellondk.so] Error 1

.h: No such file or directory NDK Android

Hi Ivgot set the gnu make buldier Cros GCC, and javah create by cygwin, . hedaer files.
And I have the .h and .cpp in the same jni direcotry: I dont understand by this error:
make all
Building file: ../jni/com_jp_algi_CoreC.cpp
Invoking: Cross G++ Compiler
g++ -I"C:\android-ndk-r5c\platforms\android-9\arch-arm\usr\include" -O0 -g3 - Wall -c -fmessage-length=0 -MMD -MP -MF"jni/com_jp_algi_CoreC.d" - MT"jni/com_jp_algi_CoreC.d" -o "jni/com_jp_algi_CoreC.o" "../jni/com_jp_algi_CoreC.cpp"
../jni/com_jp_algi_CoreC.cpp:2:31: fatal error: com_jp_algi_CoreC.h: No such file or directory
jni/subdir.mk:18: recipe for target `jni/com_jp_algi_CoreC.o' failed
compilation terminated.
make: *** [jni/com_jp_algi_CoreC.o] Error 1
Android buldier works but ...Syas this error no implementaion....of the antive. and I must to use I thnik external make, when I create .h by javah in cygwin...maybe i convert this java project in to C++-add nature..maybe there will be problem?
Ivgot this .mk:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := com_jp_algi_CoreC
LOCAL_SRC_FILES := com_jp_algi_CoreC.cpp
include $(BUILD_SHARED_LIBRARY)
.cpp:
#include <com_jp_algi_CoreC.h>
/* Header for class com_jp_algi_CoreC */
extern "C" {
JNIEXPORT void JNICALL Java_com_jp_algi_CoreC_vector
(JNIEnv *env, jobject clazz, jfloatArray input){
jfloat* flt1=NULL ;
jsize size = env->GetArrayLength(input);
jint i;
// check if array size >0 and wedont cause exception
// allocate buffer for array and get data from Java array
flt1 = new jfloat[size];
env->GetFloatArrayRegion(input,0,size,flt1);
// exception check. Always use exception check
// do stuff to the array
for (i = 0 ; i < size; i++){
flt1[i] = 1;
}
// vector(flt1);
// set result to Java array and delete buffer. And exception check of course
env->SetFloatArrayRegion(input,0,size,flt1);
delete[] flt1;
// All is ok
}
JNIEXPORT void JNICALL Java_com_jp_algi_CoreC_vector2
(JNIEnv *, jobject, jfloatArray, jobjectArray);
}
.h:
/* DO NOT EDIT THIS FILE - it is machine generated /
#include
/ Header for class com_jp_algi_CoreC */
#ifndef _Included_com_jp_algi_CoreC
#define _Included_com_jp_algi_CoreC
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_jp_algi_CoreC
* Method: vector
* Signature: ([F)V
*/
JNIEXPORT void JNICALL Java_com_jp_algi_CoreC_vector
(JNIEnv *, jobject, jfloatArray);
/*
* Class: com_jp_algi_CoreC
* Method: vector2
* Signature: ([F[[F)V
*/
JNIEXPORT void JNICALL Java_com_jp_algi_CoreC_vector2
(JNIEnv *, jobject, jfloatArray, jobjectArray);
#ifdef __cplusplus
}
#endif
#endif
and this CoreC class:
package com.jp.algi;
public class CoreC {
static {
System.loadLibrary("com_jp_algi_CoreC");
}
public native void vector(float[] input);
public native void vector2(float[] input, float[][] input2);
}
Your NDK is quite old. There are many improvements and bug fixes in the new version. The latest today is r8d, and it works on Windows without cygwin.
Regarding your code, you don't need that #include statement at all, if you simply remove the first line of your .cpp file, it will compile and link correctly.
Are you sure that the "com_jp_algi_CoreC.h" file is included inside the "com_jp_algi_CoreC.cpp" file?
Does your Android.mk file look like this?
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := module_name
LOCAL_SRC_FILES := com_jp_algi_CoreC.cpp
include $(BUILD_SHARED_LIBRARY)
Is your directory structure inside the Android project like this?
jni/
├── Android.mk
├── com_jp_algi_CoreC.h
├── com_jp_algi_CoreC.cpp
Also try to run ndk-build from the root of the project instead of Eclipse and see if there is any difference.
EDIT: Using your code I've created a test Android application and compiled the native code with
ndk-build and it all works fine.

How compile c++ project via Android NDK

I have small C++ library project with one class.
class Test
{
public:
Test(){};
~Test(){};
int SomeFunc() { return 5; }
}
I can build this class via Android NDK. (Question 1).
I can use .so file into Java application. How I can call SomeFunc method from Java code (Question 2).
Here are the steps:
1.) Create Android.mk in the project's "jni" folder:
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := main_jni
LOCAL_CFLAGS :=
LOCAL_SRC_FILES := main.cpp
LOCAL_LDLIBS :=
include $(BUILD_SHARED_LIBRARY)
2.) Create main.cpp in the "jni" folder:
#include <jni.h>
using namespace std;
#ifdef __cplusplus
extern "C" {
#endif
class Test {
public:
Test(){};
~Test(){};
int SomeFunc() { return 5; }
};
jint Java_com_example_activity_MainActivity_SomeFunc(JNIEnv *env, jobject thiz)
{
Test *test = new Test();
return test->SomeFunc();
}
#ifdef __cplusplus
}
#endif
3.) Add a call to load the library in your calling activity (MainActivity.java in this example):
static {
System.loadLibrary("main_jni");
}
4.) Define the native function in the calling activity:
native int SomeFunc();
5.) Call it from the activity:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TextView text = (TextView) this.findViewById(R.id.text);
text.setText(String.valueOf(SomeFunc()));
}
6.) Run the "ndk-build" command from the project's root folder (Note: refresh the project in Eclipse after this step)
7.) Re-build and run the application
I'm not sure I understand the questions correctly but this link could be useful to you.
I'm personally do not know much of C except for the very basics, but I look forward to getting to more C with the NDK.
Whatever code you write in c you need to define it like java_urpackagename_class_methodname then before using this code u need to first create a native method in java class like public native int ABC(); telling it that you are going to use this method.To use it do create an Android.mk or Application.mk as per your need. .so will help your java class know ,what your c code wants to do.

Jni Tutorial for android [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking us to recommend or find a tool, library or favorite off-site resource are off-topic for Stack Overflow as they tend to attract opinionated answers and spam. Instead, describe the problem and what has been done so far to solve it.
Closed 9 years ago.
Improve this question
Hi, can anyone suggest me some good resources to learn JNI for Android and some good JNI Tutorials?
Tutorial for ECLIPSE
Here is first and second small tutorials, but if you want to write a simple program that uses JNI , you may continue reading :)
Create Android application project , Once your project has been created, you’ll need to create a new folder inside the top level of the project. To do this right click on your project name → New → Folder. Name this folder jni. Than add class with name SquaredWrapper. add these code in it
package org.edwards_research.demo.jni;
public class SquaredWrapper {
// Declare native method (and make it public to expose it directly)
public static native int squared(int base);
// Provide additional functionality, that "extends" the native method
public static int to4(int base)
{
int sq = squared(base);
return squared(sq);
}
// Load library
static {
System.loadLibrary("square");
}
}
Open terminal. You must compile these code for getting header file. At first call this command.
cd src # change into the source directory
javac -d /tmp/ org/edwards_research/demo/jni/SquaredWrapper.java
Than
cd /tmp
javah -jni org.edwards_research.demo.jni.SquaredWrapper
SO you'll have header file named org.edwards_research.demo.jni.SquaredWrapper in your tmp directory.
it must be something like this
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class org_edwards_research_demo_jni_SquaredWrapper */
#ifndef _Included_org_edwards_research_demo_jni_SquaredWrapper
#define _Included_org_edwards_research_demo_jni_SquaredWrapper
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: org_edwards_research_demo_jni_SquaredWrapper
* Method: squared
* Signature: (I)I
*/
JNIEXPORT jint JNICALL Java_org_edwards_1research_demo_jni_SquaredWrapper_squared
(JNIEnv *, jclass, jint);
#ifdef __cplusplus
}
#endif
#endif
change these name for some short one for your comfort, for example square.h. Copy this header file in the jni folder of your app. Than create square.c file in same folder, copy this in it.
#include "square.h"
JNIEXPORT jint JNICALL Java_com_example_android_1jni_1second_1demo_SquaredWrapper_squared
(JNIEnv * je, jclass jc, jint base)
{
return (base*base);
}
Add this in your MainActivity.java
int x = SquaredWrapper.to4(2);
x = x*2;
Add Android.mk file in jni folder with this body
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := squared
LOCAL_SRC_FILES := square.c
include $(BUILD_SHARED_LIBRARY)
It must create library from header and cpp files.
So you have only to do some configurations by looking on my first link
Now you can compile it , be sure that your library has created and your lib directory consist it.
Tutorial for Android Studio
Let's consider you have simple android application opened by Android Studio
step 1: open Your application by Android Studio
step 2: Download NDK and set the path to NDK in local properties of your application(below/above of android sdk path) like this ndk.dir=C\:\\Android\\android-ndk-r10e
P.S. for windows double // , for linux one /
step3: Add JNI folder in the app (right click on the app -> new -> folder -> JNI Folder)
step 4 Set up the Gradle by this way:
Add this code in app/build.gradle for starting NDK
sourceSets.main {
jni.srcDirs = []
jniLibs.srcDir 'src/main/libs'
}
tasks.withType(NdkCompile) { // disable automatic ndk-build call
compileTask -> compileTask.enabled = false
}
task ndkBuild(type: Exec) { // call ndk-build(.cmd) script
if (Os.isFamily(Os.FAMILY_WINDOWS)) {
commandLine 'cmd', '/c', 'ndk-build.cmd', '-C', file('src/main').absolutePath
} else {
commandLine 'ndk-build', '-C', file('src/main').absolutePath
}
tasks.withType(JavaCompile) {
compileTask -> compileTask.dependsOn ndkBuild
}
step 4:
Create files Android.mk and Application.mk in JNI folder of the app with this bodies:
Android.mk
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := main
LOCAL_SRC_FILES := main.cpp
include $(BUILD_SHARED_LIBRARY)
Application.mk
APP_ABI := all
include $(BUILD_SHARED_LIBRARY)
In APP_ABI you choose which compilers to use. It
step 5:
We have to manually run NDK as we disable it from build.config. For creating com_example_nativedemo_app_MainActivit.h file in src\main\jn folder we have to run this command in terminal
javah -d .\jni -classpath C:\Intel\INDE\IDEintegration\android-sdk-windows\platforms\android-21\android.jar;..\..\build\intermediates\classes\debug com.example.mydemo.nativedemo.MainActivity
for windows cmd you have to give the full path of files.
For
step 6:
Add file main.cpp in JNI folder with this body:
#include <string.h>
#include <jni.h>
#include <vchat_cpptest_Hellojnicpp.h>
extern "C" {
JNIEXPORT jstring JNICALL
Java_vchat_cpptest_Hellojnicpp_stringFromJNI
(JNIEnv *env, jobject obj)
{
#ifdef __INTEL_COMPILER_UPDATE
return env->NewStringUTF("Hello from Intel C++ over JNI!");
#else
return env->NewStringUTF("Hello from default C++ over JNI!");
#endif
}
I would suggest downloading the ndk. Unzip it and browse the sample folder ndk codes. Start with the hello-jni and go further. It explains a lot with ease.
You can also browse these links and this while going through the code and keep coming back and forth.

Categories

Resources