I am trying to use the new android NDK plugin that comes with ADT to write an OpenGL ES application. I am getting a getting undefined references for all my gl functions although I have added the correct path to the NDK under Preferences -> Android -> NDK and set the correct Paths and Symbols in the project properties. I am using Windows.
And yet I still get undefined references like so:
I am using CDT 8.0.2 because apparently the newer version broke the way the NDK plugin looks for paths. I am using ADT 20.0.3. My eclipse version is Juno 4.2.0. Does anyone know why it cant find the headers that are clearly there?
Android.mk
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := libgweng
LOCAL_SRC_FILES := game.cpp
include $(BUILD_SHARED_LIBRARY)
You don't need to do this with the NDK, just write an appropriate makefile for an Android build.
Look at the source code in the hello-gl2 example that comes with the NDK; give attention to the Android.mk of this example.
Related
I'm trying to make use of a prebuilt dynamic library in a Flutter (v2.2.1) Android application.
I've placed the compiled libs into the android/app/src/main/jniLibs folder under target specific sub-folders, and they're picked up correctly by the build system and I can load the library with DynamicLibrary.open().
The library is written with Rust, but it makes use of a C++ library and I'm getting the error dlopen failed: cannot locate symbol "__cxa_pure_virtual" referenced by...
So my question is, how exactly do I tell the build system to link against the C++ runtime?
The Android 'C++ library support' page explains that the default runtime for ndk-build is none, and that I should add APP_STL := c++_shared to my Application.mk file.
Up until this point I didn't have an Application.mk file, but I could see that adding one might make sense, so I added the APP_STL definition to android/app/jni/Application.mk, and after some reading I decided that I should also add an Android.mk file (I don't know if it's actually required), with the following contents:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := foo-prebuilt
LOCAL_SRC_FILES := $(TARGET_ARCH_ABI)/libfoo.so
include $(PREBUILT_SHARED_LIBRARY)
From what I understand these then need to be picked up by Gradle, so in android/app/build.gradle I've added:
...
android {
...
externalNativeBuild {
ndkBuild {
path 'jni/Android.mk'
path 'jni/Application.mk'
}
}
}
Unfortunately this doesn't have any effect (I get the same error, and inspecting the APK shows that libc++_shared.so hasn't been included). I'm at the point where I'm thinking there's surely a simpler way to tell the build system to link against libc++_shared.so?
If I'm going down the right path, any ideas for why isn't my APP_STL definition being applied?
I guess you should put libc++_shared.so into dir:android/app/src/main/jniLibs.
I want to use some native c++ code/library in my Android application. The c++ part is heavily based on openCV.
I am aware of opencv-android-sdk and have seen plenty of detailed tutorials on how to do it with Android Studio (like this one), but these all just use the opencv-android-sdk that only supports a limited subset of openCV functions (I am not talking about those that do not make sense on a mobile device, like gpu-related functionalities, but some other functions that simply do not exist in the opencv-android-sdk and I need them for the c++ code).
Anyway, my question is: can I somehow compile and use the "full set of modules" of openCV in my Android Studio project (using NDK, etc.)?
I saw also this one, and it claims that "[it] will build most of the OpenCV modules [for android]", but it is not clear to me how to use it...
Any hint would be highly appreciated!
OK! I guess I figured it out!
Basically one needs to follow this tutorial, but just replace the path in Android.mk to point to the compiled full version of openCV, instead of openCV-Android-SDK (as well as some other small changes; for those I just copy here what I have in Android.mk and Application.mk).
Eventually, my Android.mk looks like this (OPENCVROOT need to be set properly):
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
OPENCVROOT:= /path/to/opencv-2.4.10/platforms/build_android_arm
OPENCV_CAMERA_MODULES:=on
OPENCV_INSTALL_MODULES:=on
OPENCV_LIB_TYPE:=SHARED
include ${OPENCVROOT}/OpenCV.mk
LOCAL_SRC_FILES := main.cpp
LOCAL_LDLIBS += -llog
LOCAL_MODULE := hello
include $(BUILD_SHARED_LIBRARY)
And Application.mk looks like this:
APP_STL := gnustl_static
APP_CPPFLAGS := -frtti -fexceptions
APP_ABI := armeabi-v7a
APP_PLATFORM := android-19
Just a short note on compiling openCV with Android NDK:
For compiling full openCV using NDK, one can still use the method mentioned here; the description is based on NDK-r8e, but if needed, one can download NDK-r10d and use it instead. I had to turn-off cuda-related parts in openCV source, in order to successfully compile it with NDK (just adding -D WITH_CUDA=OFF to opencv-2.4.10/platforms/scripts/cmake_android_arm.sh , in the last line, after cmake, does the job!). In case you need to have the nonfree modules (like SURF and SIFT, do NOT clone it from github, just download it in a single zip from here; I used version 2.4.10 by the way).
Now I have access to almost all openCV functions in the native c++ code that I am integrating into my Android App!
I hope this helps others, too!
You should investigate JNI (The Java Native Interface) which is a means of wrapping C libraries with Java.
Also you may want to consider getting hold of this book: Mastering OpenCV with Practical Computer Vision Projects
Which goes into this in some detail.
I recently started to use Android NDK and I’m facing some problems with shared libraries.
I created a project with Eclipse that allows me to use NDK and natives functions. But now, I would like to use another shared library that I created with QtCreator.
So here is my question. Is that possible to include a shared library to my NDK project, even if I didn’t invoke ndk-build to create it?
Let’s take an example. If I create a simple shared library like that:
g++ -Wall -shared -fPIC -o libapi.so MyDLL.cpp
Could I be able to use it on my NDK project like this (Android.mk):
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := api
LOCAL_SRC_FILES := ../sharedLibs/libapi.so
include $(PREBUILT_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := dbapi
LOCAL_SRC_FILES := dbapi.cpp
LOCAL_C_INCLUDES += ../includes
LOCAL_SHARED_LIBRARIES := api
include $(BUILD_SHARED_LIBRARY)
And of course, could I be able to use its functions on my native NDK side?
Using this method, I'm facing this error when I try to build my Eclipse project:
/libs/armeabi-v7a/libapi.so: File format not recognized
I thought my shared lib was not compatible with ndk-build (true, false?).
Thank you for your answers.
How did you build your shared lib? Is it compiled for arm, with NDK?
If not, it cannot work.
The people in the comments are indicating that you have almost certainly compiled for x86 instead of arm. (You say you are using cygwin with Windows, which will compile to x86 by default unless your windows box is an arm box, which I am guessing is not the case.)
Inside the Android ndk is a script called make-standalone-toolchain.sh. If you are in the current directory where your ndk is installed, you can use this by typing:
./android-ndk-r9/build/tools/make-standalone-toolchain.sh --platform=<your desired android platform> --install-dir=<location where you want android toolchain>
This will create a set of build tools which you can use to build arm binaries to run on your device. These tools will be named things like, e.g.
arm-linux-androideabi-gcc
Put those tools in your path and use them to build your library.
I don't know whether cygwin includes a "file" command, but you may be able to determine the architecture of your shared library by typing:
file libapi.so
If it says it's arm, you're good. If it says x86, it won't work (except on an x86 android device, that is).
I want to use libcurl in my native project. How can I integrate this library and build using ndk? Is there any post available that can guide me through the process?
I tried the docs from official site, but that's not working. FYI I am on windows platform.
Create a JNI folder within your project and add a folder for each architecture(arm, armv7,x86 etc). Place the corresponding libcurl.so files in the respective folders. Since this is a rebuilt shared binary you need to add this to your Android.mk file
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := <Curl> //add the module name here.
LOCAL_SRC_FILES := <libCurl.so> //add the .so file name here
LOCAL_C_INCLUDES := $(LOCAL_PATH)/../jni/include
include $(PREBUILT_SHARED_LIBRARY)
Create a JNI C file that uses the libraries from Curl and call the native code from Java source.
static {
System.loadLibrary("curl");
}
It shouldnt make a difference if you are on Windows platform. Adding open source liv files to Android NDK is pretty much the same process on all platforms.
No idea about windows, but as to the linker magic, see the links in
Integrating MuPDF as a library project (Android)
I'm currently implementing a custom Logging mechanism that I need to be accessible from both native and Java code. The fundamentals of the logging are implemented in C/C++ with a Java wrapper, and the two together are being built as an android Library Project.
The issue at hand is that while my Java code can access the Library project output, there doesn't seem to be a way for my native code to access the native .so or headers from the Library project. Is there an additional step I'm missing or is this just a limitation of the current ADT? More specifically, is there a makefile/eclipse configuration that will address the things I'm used to getting out of Library projects in general? (Build .so as needed, import rebuilt .so, import relevant headers for c/c++ compilation, etc.)
I don't think it's a limitation. We are supposed to declare native code dependencies in Android.mk and Application.mk
Worked out a way to get what I wanted - most of the information is (of course) in the NDK documentation, but what I was trying to do isn't 100% supported within the ADT. It should also be noted that I'm currently stuck developing in a windows environment, so much of this might be easier or unnecessary in Linux. The first key is the $(call import-module ...) macro. Within your library project, move the source files and the Android.mk folder into a named directory you can locate later. My Library project directory looked like this:
MyProject
> src
> res
v jni
- Application.mk
v MyLib
- source.cpp
- source.h
- Android.mk
I also had to edit my Application.mk to point to the project:
APP_PROJECT_PATH := <path-to-my-project>
APP_BUILD_SCRIPT := $(APP_PROJECT_PATH)/jni/MyProject/Android.mk
Annoyingly, this broke my Android.mk in ways unforseen until I added a ./ to my source files. Also you need to export your includes for linking:
LOCAL_SRC_FILES := ./source.cpp
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)
Ensure that the system path variable NDK_MODULE_PATH is set to include your library's JNI directory, e.g. <path-to-my-project>/jni (Note: I had to restart eclipse after I did this).
In the receiving application's Android.mk file (the one you'd like to link natively to your app), import the module:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := MyNativeProject
LOCAL_SRC_FILES := source.cpp
LOCAL_CFLAGS := -DANDROID_NDK -g -std=c99
LOCAL_SHARED_LIBRARIES := MyLib
include $(BUILD_SHARED_LIBRARY)
$(call import-module,android/native_app_glue)
$(call import-module, IntelLog)
At this point everything built perfectly, but the APK packager didn't like the generated .so binary being included twice (once from the Library project's natural import process, and again from the import-module call). To solve this, clean the library and don't build it again! the import-module call will build the .so and import it into your project. (Obviously, if your project only requires the Java API, you would need that .so file to be built). Congratulations! you have a functional (if not straightforward) build process with a hybrid native/Java Library