I with success compile library LibXtract to shared object libxtract.so and want to use is in second project.
In mention project I try to compile it on simple function:
#include <com_androidnative1_NativeClass.h>
#include <android/log.h>
#include "libxtract.h"
JNIEXPORT void JNICALL Java_com_androidnative1_NativeClass_showText
(JNIEnv *env, jclass clazz)
{
float mean = 0, vector[] = {.1, .2, .3, .4, -.5, -.4, -.3, -.2, -.1}, spectrum[10];
int n, N = 9;
float argf[4];
argf[0] = 8000.f;
argf[1] = XTRACT_MAGNITUDE_SPECTRUM;
argf[2] = 0.f;
argf[3] = 0.f;
xtract[XTRACT_MEAN]((void *)&vector, N, 0, (void *)&mean);
__android_log_print(ANDROID_LOG_DEBUG, "LIbXtract", "Button pushe2");
}
I have flat structure:
jni/com_androidnative1_NativeClass.c
jni/com_androidnative1_NativeClass.hjni/libxtract.h
jni/other *.h files from libxtract interface
jni/Android.mk
jni/Applicatoin.mk
library libxtract.so I put in mainproject/lib folder
my Android.mk file looks like:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES := com_androidnative1_NativeClass.c
LOCAL_MODULE := com_androidnative1_NativeClass
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/
LOCAL_LDLIBS += -llog
LOCAL_SHARE_LIBRARIES := libxtract
NDK_MODULE_PATH += $(LOCAL_PATH)/../lib/
include $(BUILD_SHARED_LIBRARY)
and I still got error:
Compile thumb : com_androidnative1_NativeClass <= com_androidnative1_NativeClass.c
SharedLibrary : libcom_androidnative1_NativeClass.so./obj/local/armeabi/objs/com_androidnative1_NativeClass/com_androidnative1_Nativ eClass.o: In function `Java_com_androidnative1_NativeClass_showText':
/home/jack/Projects/AndroidNative1/jni/com_androidnative1_NativeClass.c:20: undefined reference to `xtract'
collect2: ld returned 1 exit status
make: *** [obj/local/armeabi/libcom_androidnative1_NativeClass.so] Error 1
Code came form example of LibXtract and under C++ compile without problems, any ideas?
Your Android make file should be ...
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LIB_PATH := $(LOCAL_PATH)/../lib
LOCAL_SRC_FILES := com_androidnative1_NativeClass.c
LOCAL_MODULE := com_androidnative1_NativeClass
LOCAL_LDLIBS += -llog
LOCAL_LDLIBS += $(LIB_PATH) -lxtract
LOCAL_SHARE_LIBRARIES := libxtract
include $(BUILD_SHARED_LIBRARY)
Try this make file in your second project, and you can successfully build your code without having any error.
In the above answer all is right but exept one.
When we want to link lib we must add -L before LOCAL_LDLIBS dir as below.
LIB_PATH := $(LOCAL_PATH)/../lib
LOCAL_LDLIBS += **-L**$(LIB_PATH) -lxtract
Else it will give error as below
cannot open XXX/../lib: Permission denied
You need to tell Android NDK build scripts about your shared library. Check ${NDK}/doc/PREBUILTS.html for instructions how this can be done. They advise to add Android.mk in the same directory where you have your libXtract.so:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := libXtract
LOCAL_SRC_FILES := libXtract.so
include $(PREBUILT_SHARED_LIBRARY)
Debugging tip: I guess you are using ndk-build to build your "second project". Try running ndk-build with V=99 (try V=99 ndk-build or ndk-build V=99 - my memory failing). This will show you the the exact failing linking command. You should likely have options -lXtract and -L/path/to/libXtract/library. (Sometimes it is convenient to just copy and paste the linking command to run it manually to find the right options for successful linking, before actually fixing the build settings.)
Update: I now see #codetiger's comment seems to point to a same sort of answer (without mentioning the NDK document which is good reading - so I am not deleting this answer).
Related
I'm trying to add firebase c++ sdk to my cocos2d-x 3.14 game. So far I've create Android.mk in firebase_cpp_sdk directory:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := firebase-prebuilt
LOCAL_SRC_FILES := libs/android/$(TARGET_ARCH_ABI)/c++/libapp.a
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include
include $(PREBUILT_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := firebase-analytics
LOCAL_SRC_FILES := libs/android/$(TARGET_ARCH_ABI)/c++/libanalytics.a
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include
include $(PREBUILT_STATIC_LIBRARY)
Then in my project in Android.mk I've added:
LOCAL_C_INCLUDES += /Users/piotr/Documents/pierdoly/firebase_cpp_sdk/include
LOCAL_STATIC_LIBRARIES += firebase-prebuilt firebase-analytics
$(call import-add-path, /Users/piotr/Documents/pierdoly/firebase_cpp_sdk)
I can sync gradle and build project.
I also can
#include <firebase/app.h>
in AppDelegate.cpp (or h) and it works fine. Even Android studio can see all firebase headers and I can inspect them.
Now, in applicationDidFinishLaunching I've added this:
#if (CC_TARGET_PLATFORM != CC_PLATFORM_ANDROID)
::firebase::App* app = ::firebase::App::Create(::firebase::AppOptions());
#else
::firebase::App* firebaseApp = ::firebase::App::Create(::firebase::AppOptions(), cocos2d::JniHelper::getEnv(), cocos2d::JniHelper::getActivity());
#endif
There's also alternative version via JNICALL from AppActivity.java (to pass correct activity as some say solution above doesn't work):
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
JNIEXPORT void JNICALL Java_org_cocos2dx_cpp_AppActivity_initFirebase(JNIEnv* env, jobject thiz)
{
::firebase::App* app = ::firebase::App::Create(::firebase::AppOptions(), env, thiz);
}
#endif
Yet my problem is: it won't even compile. There's linker error:
Error:(141) undefined reference to 'firebase::App::Create(firebase::AppOptions const&, _JNIEnv*, _jobject*)'
I can clearly "go" into this function in Android Studio and I've rechecked twice parameters I'm giving. They're fine. Yet linker yells at me.
How can I fix linker? What am I missing here?
I had the same problem but found the answer:
It's about the order of the libraries being linked.
You just have to rearrange it like this:
LOCAL_STATIC_LIBRARIES += firebase-analytics firebase-prebuilt
And it should work.
Say thanks to the guys in this github issue
Cocos uses different utils for native libraries build, it can be cmake or ndk util, so check in your frameworks/runtime-src/proj.android/gradle.properties option PROP_BUILD_TYPE and change if it needs from cmake to ndk-build
then look on build.gradle at frameworks/runtime-src/proj.android/app/build.gradle it must use ndk-build correctly.
I have recently started working with NDK and am stuck with a problem. I basically want to use an external static library (.so) into my application. Here's what I've tried till now.
Create a library
1) Add a method in the Java class with native keyword
public native static void FibNR ();
2) In the terminal navigate to the project folder and run the following command
mkdir jni
javah -jni -classpath bin/classes/ -d jni/ com.example.fibonaccinative.FibLib
3) Refresh project and add a C file corresponding to the generated H file.
4) Create a Android.mk file in the JNI folder and add the following code in it
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
OPENCV_LIB_TYPE :=STATIC
LOCAL_SRC_FILES := com_example_fibonaccinative_FibLib.c
LOCAL_MODULE := com_example_fibonaccinative_FibLib
include $(BUILD_SHARED_LIBRARY)
5) Build the code using the following command
/Developer/android-ndk-r9b/ndk-build all
The above steps execute successfully and I'm able to view the results of the c code also. Now I want to create a new application and use the generated .so file (com_example_fibonaccinative_FibLib.so) into it. For this I do the following
Use the library
follow steps 1, 2 and 3 from above for the new application
4) Create a Android.mk file in the JNI folder and add the following code in it
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
OPENCV_LIB_TYPE :=STATIC
LOCAL_SRC_FILES := com_example_usingstaticlibrary_LibraryTest.c
LOCAL_MODULE := com_example_usingstaticlibrary_LibraryTest
LOCAL_SHARED_LIBRARIES :=libcom_example_fibonaccinative_FibLib.so
LOCAL_LDLIBS := -L$(SYSROOT)/usr -llog
include $(BUILD_SHARED_LIBRARY)
5) Build the code using the following command
/Developer/android-ndk-r9b/ndk-build all
I'm not sure what to do next. What I think is I need to call the function of the library into com_example_usingstaticlibrary_LibraryTest.c. But doing so gives me an error saying
'com_example_fibonaccinative_FibLib' undeclared
EDIT 1:
1) In project 2 (where I want to use the Prebuilt Shared Library (.so)) I copied the library into the 'jni' folder
2) Changed the Android.mk file with the below text.
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := libcom_example_fibonaccinative_FibLib
LOCAL_SRC_FILES := libcom_example_fibonaccinative_FibLib.so
include $(PREBUILT_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := com_example_usingstaticlibrary_LibraryTest
LOCAL_SHARED_LIBRARIES := libcom_example_fibonaccinative_FibLib
LOCAL_SRC_FILES := com_example_usingstaticlibrary_LibraryTest.c
include $(BUILD_SHARED_LIBRARY)
3) Added the .h file from the old project (com_example_fibonaccinative_FibLib.h) into the 'jni' folder
4) Changed the source of com_example_usingstaticlibrary_LibraryTest.c to
#include "com_example_usingstaticlibrary_LibraryTest.h"
#include "com_example_fibonaccinative_FibLib.h"
JNIEXPORT jlong JNICALL Java_com_example_usingstaticlibrary_LibraryTest_callLibraryFunction
(JNIEnv *env, jclass class) {
Java_com_example_fibonaccinative_FibLib_fibNR(env, class, 500l);
return -500l;
}
Clean/Build results into the following error
undefined reference to 'Java_com_example_fibonaccinative_FibLib_fibNR'
Edit 2:
With reference to this I've edited the Android.mk as follows
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := com_example_fibonaccinative_FibLib
LOCAL_SRC_FILES := libcom_example_fibonaccinative_FibLib.so
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include
include $(PREBUILT_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := com_example_usingstaticlibrary_LibraryTest
LOCAL_SRC_FILES := com_example_usingstaticlibrary_LibraryTest.c
LOCAL_SHARED_LIBRARIES := com_example_fibonaccinative_FibLib
include $(BUILD_SHARED_LIBRARY)
The NDK build command compiles the code without error. When trying to load the library it gives the following error
Exception Ljava/lang/UnsatisfiedLinkError; thrown while initializing Lcom/example/usingstaticlibrary/LibraryTest
When I remove LOCAL_SHARED_LIBRARIES := com_example_fibonaccinative_FibLib it works fine but I cannot use any function of the Prebuilt shared library.
Edit 3:
I tried a few more things including the suggestion by #jcm but nothing worked. I'm now attaching the source code. It has both the projects (Cleaned version to reduce size).
FibonacciNative: Contains the first project.
UsingStaticLibrary: Contains the second project. I intend to use the Prebuilt Shared Library of the first project into the second one.
You say you want to include a precompiled static library .a, but the file you reference is a shared library .so. If you still want to include a static library, here comes the solution and explanation:
LOCAL_SHARED_LIBRARIES :=libcom_example_fibonaccinative_FibLib.so
You're trying to include the static library as a shared one, looks like an accidental slip from using the previous shared library entry as reference :).
Upon that, Android makefiles still requires you to actually make a module for the external library.
include $(CLEAR_VARS)
LOCAL_MODULE := com_example_fibonaccinative_FibLib
LOCAL_SRC_FILES := com_example_fibonaccinative_FibLib.a
include $(PREBUILT_STATIC_LIBRARY)
Then you can simply add it as a dependency:
LOCAL_STATIC_LIBRARIES := com_example_fibonaccinative_FibLib
But if you're actually trying to include an external shared library. You would need to change the above to the following:
include $(CLEAR_VARS)
LOCAL_MODULE := com_example_fibonaccinative_FibLib
LOCAL_SRC_FILES := com_example_fibonaccinative_FibLib.so
include $(PREBUILT_SHARED_LIBRARY)
and include it as a shared library.
LOCAL_SHARED_LIBRARIES := com_example_fibonaccinative_FibLib
Hope I helped!
Disclaimer: I have not actually tried to compile an example, simply referencing my knowledge and quick research.
References:
Android NDK: Static library used is different than precompiled library specified
As you're including libcom_example_fibonaccinative_FibLib.so as LibraryTest's shared library, in your java static method, you should load it before loading LibraryTest:
System.loadlibrary(com_example_fibonaccinative_FibLib);
System.loadLibrary(LibraryTest);
Update:
After checking your code, LibraryTest.java should look like:
package com.kochartech.usingstaticlibrary;
public class LibraryTest {
public native static long callLibraryFunction();
static {
System.loadLibrary("com_kochartech_fibonaccinative_FibLib");
System.loadLibrary("com_kochartech_usingstaticlibrary_LibraryTest");
}
}
I have come across a problem with trying to compile cURL with SSL support into an app.
So far, I have successfully compiled the openSSL package into libcrypt.so and libssl.so.
I believe I have successfully compiled a version of libcurl.a with SSL support using the configure script and running it through the cross-chain compiler found in the NDK (under a linux environment).
Now, I am attempting to write a .so library under Eclipse that can be called by the Java code of an Android App.
Here is the file structure so far:
Project Folder ---> jni ---> include ---> curl ---> curl headers
| |
| -> openssl ---> ssl and crypto headers
|
-> libcrypto.so
-> libssl.so
-> libcurl.a
-> jniProcessRequest.c
-> Android.mk
Android.mk reads:
LOCAL_PATH := $(call my-dir)
MY_PATH := $(LOCAL_PATH)
include $(CLEAR_VARS)
LOCAL_PATH := $(MY_PATH)
LOCAL_MODULE := crypto
LOCAL_SRC_FILES := libcrypto.so
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/openssl/
include $(PREBUILT_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := ssl
LOCAL_SRC_FILES := libssl.so
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/openssl/
include $(PREBUILT_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := curl
LOCAL_SRC_FILES := libcurl.a
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/curl/
include $(PREBUILT_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := JNIProcessRequest
LOCAL_SRC_FILES := JNIProcessRequest.c
LOCAL_SHARED_LIBRARIES := crypto ssl
LOCAL_STATIC_LIBRARIES := curl
LOCAL_LDLIBS := -llog
include $(BUILD_SHARED_LIBRARY)
jniProcessRequest.c:
#include <jni.h>
#include <stdlib.h>
#include "include/curl/curl.h"
#include <android/log.h>
JNIEXPORT void JNICALL Java_com_example_jniprocessrequest_MainActivity_jniProcessRequest(JNIEnv * env, jobject obje){
CURL *conn;
conn = curl_easy_init();
}
Every time I attempt to compile the above, I have undefined reference errors in Eclipse:
make: *** [obj/local/armeabi/libJNIProcessRequest.so] Error 1
undefined reference to 'curl_easy_init'
I am thinking this is some sort of linkage error but am struggling to find where the error is occurring. I have spent nearly two days trying all different methods of placing the shared libraries in differing places, switching the static libcurl with a shared libcurl, altering the Android.mk file and following tutorials on how to get cURL working in Android.
Any help would be greatly appreciated!
I believe that the problem was stemming from an incorrectly built libcurl.a static library. I replaced my library with one that was compiled by a user on GitHub and without changing any code, the linkage errors disappeared.
You use curl as a prebuilt module.
As stated by the NDK documentation you should take care to wrap it under include $(CLEAR_VARS) and (most importantly) include $(PREBUILT_STATIC_LIBRARY) directives as follow:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := foo-prebuilt
LOCAL_SRC_FILES := libfoo.a
include $(PREBUILT_STATIC_LIBRARY)
Right after take care to wrap your JNIProcessRequest module with include $(CLEAR_VARS) and include $(BUILD_SHARED_LIBRARY).
For more details please refer to the docs/PREBUILTS.html section that you can find within your Android NDK folder (it looks like this).
So I'm attempting to use libopus on my native code for an Android application.
My Android.mk file looks like this:
PLATFORM_PREFIX := /opt/android-ext/
LOCAL_PATH := $(PLATFORM_PREFIX)/lib
include $(CLEAR_VARS)
LOCAL_MODULE := libopus
LOCAL_SRC_FILES := libopus.a
include $(PREBUILT_STATIC_LIBRARY)
# I have to redeclare LOCAL_PATH because the library is in /opt/android-ext/
# and my project is somewhere else. Not very elegant.
LOCAL_PATH := /home/sergio/workspace/Project/jni
include $(CLEAR_VARS)
LOCAL_MODULE := opusUtilsNative
LOCAL_SRC_FILES := opusUtilsNative.c
LOCAL_C_INCLUDES += $(PLATFORM_PREFIX)/include
LOCAL_STATIC_LIBRARIES := android_native_app_glue libopus
include $(BUILD_SHARED_LIBRARY)
And my code in opusUtilsNative.c looks like this:
#include "opusUtilsNative.h"
#include <opus/opus.h>
#include <opus/opus_types.h>
JNIEXPORT jbyteArray JNICALL Java_Project_OpusUtils_encode
(JNIEnv * je, jclass jc, jbyteArray data){
int rc;
opus_int16 * testOutBuffer;
unsigned char* opusBuffer;
OpusDecoder *dec;
dec = opus_decoder_create(48000, 2, &rc);
return data;
}
And when I try to build it, it works fine only if I remove the line that uses the "opus_decoder_create" function. Else I will get this:
error: undefined reference to 'opus_decoder_create'
I can see that opus_decoder_create is clearly defined on opus.h, which is clearly being included since if I exclude that line, I'll get an error regarding the opus_int16 and OpusDecoder declarations. How come some definitions are being included and some aren't?
Any help will be greatly appreciated.
This was tricky. After digging around for a bit, I realized I hadn't cross-compiled the opus library correctly, and I didn't have an ARM binary after all.
A good way to verify if your library was cross-compiled correctly:
cd /opt/android-ext/lib #Or wherever the .a file is
ar x libopus.a
file tables_LTP.o #Or any of the .o files generated by ar x
The output should look like this:
tables_LTP.o: ELF 32-bit LSB relocatable, ARM, version 1 (SYSV), not stripped
Otherwise, you might want to double-check your cross-compilation process.
It's error from linker, not from compiler. You forgot to add reference to correspondent libraries to your Android.mk file, do smth like this:
LOCAL_LDLIBS += -lopus
I forgot to integrate one key library
LOCAL_LDLIBS := -lGLESv2
This fixed my problem.
when I tried the NDK build command here is the error i got
D:\AndroidWorkSpace\cppTestProj>D:\android-ndk-r8b-windows\android-ndk-r8b\ndk-b
uild.cmd
Android NDK: WARNING: Unsupported source file extensions in jni/Android.mk for m
odule cppTestProj
Android NDK: LOCAL_SRC_FILES :=
"Compile++ thumb : cppTestProj <= maintestapp.cpp
jni/maintestapp.cpp:1:19: fatal error: iostream: No such file or directory
compilation terminated.
make: *** [obj/local/armeabi/objs/cppTestProj/maintestapp.o] Error 1
The JNI folder has the following files:
maintestapp.cpp
Test_array_type.cpp
Test_array_type.h
Could u pls let me know the issue. Im not using Cygwin for the same. Am I missing any files?
Here is the make file
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := cppTestProj
LOCAL_SRC_FILES := LOCAL_SRC_FILES := maintestapp.cpp \
Test_array_type.cpp
include $(BUILD_SHARED_LIBRARY)
here is the cpp file
#include<iostream>
#include"Test_array_type.h"
#include<stdio.h>
#include<conio.h>
using namespace std;
int main()
{
Test_array_type test_array;
Test_array_type *ptest_array1;
test_array.AddToList(10);
test_array.AddToList(20);
test_array.AddToList("Basha");
test_array.PrintList();
ptest_array1 = test_array.clonelist();
test_array.DeleteFromList(3);
test_array.AddToList(10);
test_array.AddToList(20);
test_array.AddToList(30);
test_array.AddToList(40);
test_array.AddToList(true);
test_array.AddToList("Java Beon APP");
test_array.PrintList();
ptest_array1->PrintList();
getch();
return true;
}
you should not run the 'ndk-build' command from your projects jni folder. To execute the Android.mk file run ndk-bild command within your root directory of project.
Your Android.mk should be look like this
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := cppTestProj
LOCAL_SRC_FILES := maintestapp.cpp \
Test_array_type.cpp
include $(BUILD_SHARED_LIBRARY)
Then run your ndk-build command
You can see this link for sample Android.mk file
Update:
static {
System.loadLibrary("hello-jni");
}
for more information please refer HelloJni.java file of sample project.
Thanks
you need to add LOCAL_C_INCLUDES and include your visual C++ include folders, since you are obviuosly working with it.