Environment: Latest NDK + Eclipse Juno + ADT + CDT. Everything is up to date.
When I try to debug my Android application natively, I get the following error:
warning: Unable to find dynamic linker breakpoint function.
GDB will retry eventurally. Meanwhile, it is likely
that GDB is unable to debug shared library initializers
or resolve pending breakpoints after dlopen().
To ensure it is not my specific application, I created a simple dummy application. Here are the steps I took.
From Eclipse, create a new Android application project (with min-sdk 16 and target-sdk 21)
Added a class:
package com.test.mytest1;
public class MyNative {
static {
android.os.Debug.waitForDebugger();
System.loadLibrary("mytest1");
}
native public static void init();
}
Note that I have added a line to wait for the debugger to initialize.
Called MyNative.init() from MainActivity's onCreate() method.
From preferences, fixed NDK to point to C:\adt\ndk directory.
From the project menu, selected Android Tools-->Add Native Support.
From Properties->C++ Build, set build command to "ndk-build NDK_DEBUG=1"
Here is the code in mytest1.cpp:
static int x = 0;
JNIEXPORT void JNICALL Java_com_test_mytest1_MyNative_init(JNIEnv *, jclass)
{
x++;
}
Added Application.mk in jni directory:
APP_ABI := armeabi-v7a
APP_PLATFORM := android-16
Now, when I try to run the app as native application, it fails with the above mentioned message.
When I look at the apk file, lib/armeabi-v7a does contain gdbserver as well as libmytest1.so files.
The app does work. If I add a log() statement in my native method, it does get displayed in LogCat.
I am confused and tired. A simple thing like thing should just work. Wondering if you can share what you did differently to make it work. Regards.
android.os.Debug.waitForDebugger() is for JAVA debugging.
To debug Native code add sleep(seconds) before your first breakpoint , that's way gdb have to to connect gdbserver
JNIEXPORT void JNICALL Java_com_test_mytest1_MyNative_init(JNIEnv *, jclass)
{
sleep(10);
x++;
}
Related
I'm a beginner on Android NDK, and less aware of C++. I have written some logic using C++ and then build them to .so file, then use it with JNI for my Android project, but sometimes it will raise crash in .so files.
I want to quickly fix this problem, I want to know if I can use try-catch syntax to my C++ code? (I tried, but it always reports compile error.) If yes, how can I do it?
C++ codes:
JNIEXPORT void JNICALL Java_xxoo_com_xxoo_model_ARDrawModel_draw(JNIEnv * env, jobject obj) {
try {
if(controller)
{
controller->Update(/*float dt*/);
controller->DrawGLScene();
}
} catch (int a) {
LOGD("drawModel---exception");
}
}
Compile error:
error: exception handling disabled, use -fexceptions to enable
Yes. you can use try catch in c++ NDK code, but it will not catch all native crashes.
And as your error says, you need to explicitly enable exceptions feature while compiling NDK code. To do so add
APP_CPPFLAGS += -fexceptions
to Application.mk file.
If you want to catch all possible NDK crashes check out https://github.com/xroche/coffeecatch library.
The title says it all. I'm using NDK to build a native library for use with Unity (the game engine, not the Ubuntu shell). I already have much of the code in place and it works on my Xperia Z Ultra which runs Android 4.4.4. However, recently I sent the app to some other people to test on their phones, and it worked on none of their phones. They were using Android 4.0 and 4.1, so I tried running the app on my own Android 4.0.4 device (an old Xperia Mini Pro) and had the same problem. After much narrowing down, I've found out that the root of the problem is including OpenCV in the build, even if it's not referenced at all.
Here's the code I have now. First, the simplest CPP file you've seen:
//Test.cpp:
extern "C"
{
int Test(int a, int b)
{
return a + b;
}
}
Note how it doesn't even include anything from OpenCV. The makefile (or whatever it's called in the context of NDK, I'm mostly a Windows/Visual Studio person) is:
#Android.mk:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
#---------------------------
#note: if I comment these lines out, the library works just fine.
#if I don't, it won't load at all.
#---------------------------
OPENCV_PACKAGE_DIR := D:\Eclipse\OpenCVAndroid\OpenCV-2.4.9-android-sdk
include $(OPENCV_PACKAGE_DIR)/sdk/native/jni/OpenCV.mk
LOCAL_MODULE := Test
LOCAL_SRC_FILES := Test.cpp
include $(BUILD_SHARED_LIBRARY)
Building this project gives me a "libTest.so" file. I put this into my Unity project, at Assets/Plugins/Android/ (I've also tried putting it in Plugins/Android/libs/armeabi-v7a/, no luck). I also have a script inside unity which invokes the library:
//TestNative.cs:
using UnityEngine;
using System.Collections;
using System.Runtime.InteropServices;
public class TestNative : MonoBehaviour
{
[DllImport("Test")]
public static extern int Test(int a, int b);
void OnGUI()
{
try
{
GUI.Label(new Rect(0, 0, 100, 100), "2 + 3 = " + Test(2, 3));
}
catch (System.Exception e)
{
GUI.Label(new Rect(0, 0, 600, 400), e.GetType().ToString() + " " + e.Message + "\n" + e.StackTrace);
}
}
}
When I run this on my Z Ultra, it works just fine. When I run it on the Mini Pro, it fails with the exception "DllNotFoundException: Test". I've checked logcat for errors, and this is what it says:
01-06 06:46:27.660: D/dalvikvm(11135): Trying to load lib /mnt/asec/com.cet.sna2-2/lib/libTest.so 0x2bb86638
01-06 06:46:27.660: D/dalvikvm(11135): Trying to load lib /mnt/asec/com.cet.sna2-2/lib/libTest.so 0x2bb86638
01-06 06:46:27.660: E/Unity(11135): Unable to find Test
It doesn't say anything else, it just fails. The fact that it works on 4.4.4 makes me think it might have something to do with build configurations or something like that, but I can't figure out what it is. Any ideas? Thanks.
I found out, after much trial and error, that the reason for the error is that Android somehow manages to mess the library dependencies up. The work-around is to manually load the libraries in the specific order of their dependencies, using LoadLibrary. This can be done in Unity using AndroidJavaClass to avoid having to write an entire jar library just for loading the native ones.
You have to build a .so that correspond to the architecture of the device your are using.
You should look at this link :
https://developer.nvidia.com/AndroidWorks
It provides useful tools to develop on Android with Visual Studio
You can easily configure an Android Dynamic Library (.so) that correspond to the architecture you need :)
I made a Unity3d project working with C/C++ Dll.
So first I made the dll in Visual studio.
// mydll.cpp
#define EXPORT_API __declspec(dllexport)
extern "C" {
int EXPORT_API add(int a, int b)
{
return a+b;
}
}
And I added this dll into my Unity3D project and called
// C# script in Unity3D
public class TestDll : MonoBehaviour {
[DllImport("mydll")]
private static extern int add (int a, int b);
void Start() {
int a = add (100, 200);
}
}
This code works well and I got the correct result in Unity3D editor.
So I built this project to android platform and got an apk.
I installed and run this apk on my android device but the app doesn't work.
The app didn't run the Dll function.
Whats the matter? I tried to find out the solution in Google and here, but didn't get anything, yet.
Please help me.
Thanks.
Your dll must be in Plugins folder for Windows, it can work for Editor too. for Android you must replace in Plugins/Android folder. Build and write me ok
LearnCocos2D's comment is accurate.
To get Unity to DllImport() a shared library on Android, you must use an NDK compiler and specify a compile config for your target Android platform. Moreover, Unity requires you to specify the architecture of the Android platform in the build settings, eg.. "arm v7" vs "arm64".
As an aside, in Unity 2019.4 - selecting "Load on Startup" in the inspector page of my .so elicits a "DLLNotFoundException".
Overview of this: https://docs.unity3d.com/2019.4/Documentation/Manual/AndroidNativePlugins.html
NDK's CMake guide for getting you started on compiling correctly: https://developer.android.com/ndk/guides/cmake
Android/NDK project, worked with NDK versions all the way up to r8c. Under 8d and 8e, I get a compilation error message on the armeabi-v7a build:
Compile++ thumb : myproject <= MyFile.cpp
C:\cygwin\tmp\ccFXOc2F.s: Assembler messages:
C:\cygwin\tmp\ccFXOc2F.s:1935: Error: can't resolve `.data.rel.ro.local' {.data.rel.ro.local section} - `.LPIC44' {*UND* section}
The armeabi, MIPS, and x86 builds for the same project are successful.
It's reliably popping up on the same file. The file is nothing special - vanilla C++, it compiles and works on numerous other platforms (iOS, Windows, NDK r8c to name some). No STL. It does define a healthy amount of string constants though (AKA initialized read/only data). What could be going on?
Already tried a full rebuild, even deleted the obj folder altogether.
The C++ flags are:
LOCAL_CPPFLAGS := -fshort-wchar -fsigned-char -Wno-psabi
I know NDK comes with several versions of GCC; might a toolchain change help? How exactly?
Surely looks like a compiler bug to me. It's related to indexed access to a large chunk of static const data. When I've slightly reformulated a perfectly innocent statement, the error message went away.
Used to be:
//In global scope
static const LPCWSTR Comments[] = {L"A lot of strings here", L"String 2", L"String 3" /* and many more */ }:
void SomeMethod()
{
DoSomething(Comments[i]); //That was the offending line - commenting it out would get rid the error
}
Replaced with:
void SomeMethod()
{
static LPCWSTR pComments = 0;
if(!pComments)
pComments = Comments;
DoSomething(pComments[i]); //Now it works.
}
Ooky, spooky stuff.
I'm trying to use the NDK with C++ and can't seem to get the method naming convention correct. my native method is as follows:
extern "C" {
JNIEXPORT void JNICALL Java_com_test_jnitest_SurfaceRenderer_drawFromJni
(JNIEnv* env, jclass c)
{
//
}
}
with a header wrapped in extern "C" {} aslo.
Everything compiles fine, creates a .so file and copies to the libs folder under my project, but when I debug and run in Eclipse I keep getting a log cat message that of "no implementation found for native...". Is there something i'm missing as all the NDK examples are in C?
Thanks.
There are a couple of things that can lead to "no implementation found". One is getting the function prototype name wrong, another is failing to load the .so at all. Are you sure that System.loadLibrary() is being called before the method is used?
If you don't have a JNI_OnLoad function defined, you may want to create one and have it spit out a log message just to verify that the lib is getting pulled in successfully.
You already dodged the most common problem -- forgetting to use extern "C" -- so it's either the above or some slight misspelling. What does the Java declaration look like?
An additional cause for this error: your undecorated native method name must not contain an underscore!
For example, I wanted to export a C function named AudioCapture_Ping(). Here is my export declaration in C:
JNI_EXPORT int Java_com_obsidian_mobilehashhost_MainActivity_AudioCapture_Ping(JNIEnv *pJniEnv, jobject object); //Notice the underscore before Ping
Here was my Java class importing the function:
package com.obsidian.mobileaudiohashhost;
...
public class MainActivity extends Activity {
private native int AudioCapture_Ping(); // FAILS
...
I could not get Android to dynamically link to my native method until I removed the underscore:
JNI_EXPORT int Java_com_obsidian_mobilehashhost_MainActivity_AudioCapturePing(JNIEnv *pJniEnv, jobject object);
package com.obsidian.mobileaudiohashhost;
...
public class MainActivity extends Activity {
private native int AudioCapturePing(); // THIS WORKS!
...
I had the same problem, but to me the error was in the file Android.mk. I had it:
LOCAL_SRC_FILES := A.cpp
LOCAL_SRC_FILES := B.cpp
but should have this:
LOCAL_SRC_FILES := A.cpp
LOCAL_SRC_FILES += B.cpp
note the detail += instead :=
I hope that helps.
Called extern "C" as provided in the automatically-generated Studio example, but forgot to wrap the entire rest of the file, including following functions, in {} brackets. Only the first function worked.
An additional reason: Use LOCAL_WHOLE_STATIC_LIBRARIES instead of LOCAL_STATIC_LIBRARIES in android.mk. This stops the library from optimizing out unused API calls because the NDK cannot detect the use of the native bindings from java code.
There is a cpp example under apps in ndk:
https://github.com/android/ndk-samples/blob/master/hello-gl2/app/src/main/cpp/gl_code.cpp
Use javah (part of Java SDK). Its the tool exactly for this (generates .h header from .class file).
If your package name includes _ character, you should write 1(one) after _ character as shown below:
MainActivity.java
package com.example.testcpp_2;
native-lib.cpp
JNICALL
Java_com_example_testcpp_12_MainActivity_stringFromJNI(
I try all above solutions, but no one can solved my build error(jni java.lang.UnsatisfiedLinkError: No implementation found for...),
at last I found that I forget to add my verify.cpp source file to CMakeList.txt add_library segement(verify.cpp is auto generate by Ctrl + Enter short key, maybe other file name), hope my response can help some one.
my build environment: Gradle + CMake
I Faced the same problem, and in my case the reason was that I had underscore in package name "RFID_Test"
I renamed the Package and it worked.
Thanks user1222021
I faced the same problem twice. It happened, that the phone I tried to start the app from Android Studio used an API level that I haven't downloaded yet in Android Studio.
Upgrade Android Studio to the latest version
Download the necessary API from within Android Studio