about mangled name of functions in c++ - android

ı have closed source shared library that links against libmedia.so from android
but unforunatly in >android 5.0 ABI changes that made by google broke my closed source lib (thanx google)
now ı have the following error --> dlopen failed cannot locate symbol "_ZN7android11MediaPlayer13setDataSourceEPKcPKNS_11KeyedVectorINS_7String8ES4_EE" referenced by "mylib.so"
then ı hexedited my closed source library(mylib.so) to load myhack.so (that ı built myself) instead of libmedia.so (so ı simply made a trick)
here is the Android.mk of myhack.so library:
include $(CLEAR_VARS)
LOCAL_SRC_FILES := hack.cpp
LOCAL_SHARED_LIBRARIES := libmedia
LOCAL_MODULE := myhack
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE_CLASS := SHARED_LIBRARIES
include $(BUILD_SHARED_LIBRARY)
and here is the hack.cpp:
extern "C" void _ZN7android11MediaPlayer13setDataSourceERKNS_2spINS_17IMediaHTTPServiceEEEPKcPKNS_11KeyedVectorINS_7String8ES9_EE();
extern "C" void _ZN7android11MediaPlayer13setDataSourceEPKcPKNS_11KeyedVectorINS_7String8ES4_EE() {
return _ZN7android11MediaPlayer13setDataSourceERKNS_2spINS_17IMediaHTTPServiceEEEPKcPKNS_11KeyedVectorINS_7String8ES9_EE();
}
let me explain a bit:
1-as I said I hexedited my closed source lib to load myhack.so instead of libmedia.so (source file and android.mk file of myhack.so are in above)
2-I linked myhack.so to libmedia.so(as you can see) to provide other libmedia functions via myhack.so
LOCAL_SHARED_LIBRARIES := libmedia
3-
lost symbol: _ZN7android11MediaPlayer13setDataSourceEPKcPKNS_11KeyedVectorINS_7String8ES4_EE
current symbol in libmedia.so: _ZN7android11MediaPlayer13setDataSourceERKNS_2spINS_17IMediaHTTPServiceEEEPKcPKNS_11KeyedVectorINS_7String8ES9_EE
so if lost symbol is called, it will return original function
my question is should I use extern "C" void or extern "C" int..... int or void? which one? setDataSource is a function and I dont think it is returning integer value so it should be void ı think but ım not %100 sure
could anyone help me please? thanx

Sooner or later you will get in troble with it. I remember problems with skia on project I work on. Some vendors were doing small changes with interfaces and that was causing various crashes.
To find return type you can investigate sources for android, steps are below:
You can use https://demangler.com/, to see signature of your function, it should be:
android::MediaPlayer::setDataSource(android::sp<android::IMediaHTTPService> const&, char const*, android::KeyedVector<android::String8, android::String8> const*)
now lets search android sources for such signature, you can find it here:
http://androidxref.com/6.0.1_r10/xref/frameworks/av/media/libmedia/mediaplayer.cpp#148
so its return type is status_t, which is typedef int status_t;, so as you have assumed its int.

Related

Trouble with undefined reference to Callstack library

I try to build a cpp file as below to an executable on the Android platform. Therefore, by calling dumping_callstack(), I can get call stack of my executable in run time. But there are some errors。
cpp file:mycallstack.cpp
#include <utils/CallStack.h>
extern "C" void dumping_callstack()
{
CallStack stack("haha");
}
mycallstack.h
void dumping_callstack();
test.c
#include <mycallstack.h>
main()
{
dumping_callstack();
}
android.mk
LOCAL_SRC_FILES += mycallstack.cpp
LOCAL_SHARED_LIBRARIES := libc libcutils liblog libutils
then compile.
error: undefined reference to 'android::CallStack::CallStack(char const*,int)'
error: undefined reference to 'android::CallStack::~CallStack()'
In android 9.0, you should use libutilscallstack.
Look "android/system/core/libutils/Android.bp" for more details.
The implementation of CallStack::CallStack and CallStack::~CallStack isn't provided to the compiler/linker.
You might forgot to link it to the corresponding object file/library, I suggest you to read the documentation, there might be some information about linking. Sometimes it can help to just compile it with the -static switch, this makes the executable almost standalone, some libraries even require to be linked staticly.
It might also be the case, that the implementation is not available for release builds, I think the CallStack-class could only be available for debugging.

NDK for beginner : where/how to add source files?

I'm trying to use the NDK, and I've been working with official samples to get started. I've managed to get the "Hello JNI" sample working :
https://github.com/googlesamples/android-ndk/tree/master/hello-jni
(I work with Android Studio)
But I don't know how to add source files to the project. So, for example, the JNI function provided is (I removed macros that aren't useful for this) :
jstring Java_com_example_hellojni_HelloJni_stringFromJNI( JNIEnv* env,
jobject thiz )
{
return (*env)->NewStringUTF(env, "Hello from JNI !");
}
Let's say I want to get the string from a C function "getString()", defined as below:
const char* getString()
{
return "Hello from getString()";
}
//Then, JNI function becomes
jstring Java_com_example_hellojni_HelloJni_stringFromJNI( JNIEnv* env,
jobject thiz )
{
return (*env)->NewStringUTF(env, getString());
}
If I create a getString.h where I declare the function, and put the implementation in my current and only one source file, everything works like a charm. So, headers do work.
However, If I create a GetString.c file where I put the implementation, my code stops compiling. I do understand it's because GetString.o doesn't get linked (or even compiled ? I don't know), but I have no idea about how to tell Android Studio to compile both hello-jni.c (sample's source fil) and GetString.c
Should I get my hands dirty and modify gradle files ?
I also heard about a file called Android.mk which acts like a makefile, but I haven't found it in the project. If it's mandatory, should I create it, and what to put in it ? If it's not, how does the IDE knows he must build hello-jni.c ? (AKA "how did the project get configured before I modified it")
If you need any information about java-side things or gradle scripts, just have a look on the github link :)
Well, a bit of testing was enough to confirm what I thought. I just had to create Android.mk :
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES := hello-jni.c, GetString.cpp
LOCAL_MODULE := hello-jni
include $(BUILD_SHARED_LIBRARY)

Using opencv in native code for Android app development

I have namespace error building with ndk-build for native code in my Android app. The error sample is
C:/adt-bundle-windows-x86/ndk/sources/cxx-stl/gnu-libstdc++/4.6/include/bits
/allocator.h:54:1: error: unknown type name 'namespace'
C:/adt-bundle-windows-x86/ndk/sources/cxx-stl/gnu-libstdc++/4.6/include/bits
/allocator.h:55:1: error: expected ',' or ';' before '{' token
For OpenCV settings, my Application.mk file is
APP_STL := gnustl_static
APP_CPPFLAGS := -frtti -fexceptions
APP_ABI := armeabi
APP_PLATFORM := android-10
That means I am using gnu-libstdc++ in compiling the native code.
My jni.c has c extension. That is I receive from my third party and they prefer in .c extension as if they have to change to .cpp extension, they have to change a lot in their other libraries.
So far is OK, I did all project settings for OpenCV for native development and if I do ndk-build, I can make .so libraries.
The problem of those namespace error happened when I include OpenCV's header file #include <opencv2/contrib/detection_based_tracker.hpp> into jni.c and I got a lot of name space error. If I include that #include <opencv2/contrib/detection_based_tracker.hpp> into cpp file, no error.
My questions are
(1)Is the error is because of using .hpp file in .c file?
(2)If I have no choice and have to use that .c file, is there way around to remove that error?
Thanks
My assumption would be that the file is compiled as a "C" file instead of a "C++" file because of the extension ".c". That means you cannot use any "C++" Code in your jni.c, wike classes or namespaces. These are obviously used however in your file "detection_based_tracker.hpp" that you are using.
So the problem is not that you include a file named ".hpp", but that this file contains "C++" code wich the "C" compiler cannot handle.
One solution to this problem is to only use the "C" functions in opencv (for example "opencv2/imgproc/imgproc_c.h" instead of "opencv2/imgproc/imgproc.hpp"). However, your function "detection_based_tracker.hpp" might not have a "C" version, as far as I can see.
The other option is to add a second file "function.cpp" with the "C++" functions that use opencv. The functions from "function.cpp" can be declared in a file "functions.h" and included in your "jni.c", so you can still use opencv c++ functions. Be careful to only use C style functions then, though (no classes, namespaces, ...) in your "function.h" file, otherwise you will have the same problems as before.

OpenCV Android NDK Project will not build

I am using OpenCV 2.4.4 with Eclipse Juno on Ubuntu.
My problem is similar to this one OpenCV for android sample programs showing error
But is now weirding me out. I spent most of my weekend trying to get the ndk and opencv library to play nice and still I cannot get it to work. I have in my test C++ cpp file with the following includes -
#include <jni.h>
#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <cstdlib>
using namespace cv; //this is a problem
...
...
And it tells me when I try to build that "namespace cv cannot be found".
Oh well, I must have written some path wrong or am not using the correct library, right?
Wrong.
In the terminal, ndk-build builds the .so files without any errors. I can see them plain as day in the project folder.
But if I try to do build in eclipse, i.e. build the apk for tesitng on a virtual device or real device, then I get the namespace cv error and the build fails and then in the cpp file cv is underlined red and in eclipse the file is marked red and I can't even attempt to build until this file is "corrected".
Clearly I'm doing something wrong. But if I close my eclipse project and then reopen it, the cpp file is no longer marked red and I can make an apk build. If I attempt to open the cpp file the red returns and no more builds can happen until I go through the project close/open rigmarole.
I honestly don't know what the cause of the problem is. Any help would be greatly appreciated.
My android.mk file:
include $(CLEAR_VARS)
OPENCV_CAMERA_MODULES:=off
OPENCV_INSTALL_MODULES:=on
OPENCV_LIB_TYPE:=STATIC
include /the/correct/path/tp/opencv/sdk/native/jni/OpenCV.mk
LOCAL_MODULE := mylib
LOCAL_SRC_FILES := mylib.cpp
include $(BUILD_SHARED_LIBRARY)
Application.mk
APP_STL := gnustl_static
APP_CPPFLAGS := -frtti -fexceptions
APP_ABI := all #i have tried various targets
APP_PLATFORM := android-8
APP_MODULES := mylib
I didn't think it would be this difficult. I should add that I have successfully used opencv with Android in anothe rproject I built on WIndows with Eclipse 3.5 (I think) and OpenCV 2.4.2
EDIT
I also want to say that I just did a quick 'n dirty test opencv operation. I wrote a quick Sobel function and called it as a native function in a Java file and "sobelled" a bitmap successfully. Of course, I still had to close/open my project to do this.
Hi I had same problem with you and after I added below "opencv android sdk" path that include problem disappeared.
exp : C:\project\OpenCV-2.4.6-android-sdk\sdk\native\jni\include
switch the path with your opencv-android-sdk path.
I know that's maybe too late, but in my case (Windows+Eclipse) I correct this problem just changing the backslash "\" to slash "/" in the Path and Symbols include of opencv jni libs.
Example:
Wrong H:\opencv\sdk\native\jni\include
Correct H:/opencv/sdk/native/jni/include

Linking .a compiled library and own shared library Android NDK r8b

I'm encountering an issue with linking C libraries in my Android project using the Android NDK r8b.
I built with the toolchain for ARM the cURL library (no SSL) and it provided me a libcurl.a file and a libcurl.so.4.2.0 one.
I also created a C file to provide functions to my Java code and to use the cURL library.
Android.mk
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE:= libcurl
LOCAL_SRC_FILES := libcurl.a
include $(PREBUILT_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := curljni
LOCAL_SRC_FILES := curljni.c
LOCAL_STATIC_LIBRARIES := libcurl
include $(BUILD_SHARED_LIBRARY)
and now my C file
#include <string.h>
#include <jni.h>
#include <stdio.h>
#include <stdlib.h>
jstring Java_test_curljni_MainActivity_stringFromJNI(JNIEnv* env, jobject thiz)
{
CURL *curl;
CURLcode
......
}
When I try to build with the ndk-build command from my project folder, here's the output error :
Compile thumb : curljni <= curljni.c
jni/curljni.c: In function 'Java_test_curljni_MainActivity_stringFromJNI':
jni/curljni.c:8:3: error: unknown type name 'CURL'
jni/curljni.c:9:3: error: unknown type name 'CURLcode'
jni/curljni.c:11:8: warning: assignment makes pointer from integer without a cast [enabled by default]
jni/curljni.c:13:28: error: 'CURLOPT_URL' undeclared (first use in this function)
jni/curljni.c:13:28: note: each undeclared identifier is reported only once for each function it appears in
/cygdrive/c/android-ndk-r8b/build/core/build-binary.mk:252: recipe for target `obj/local/armeabi/objs/curljni/curljni.o' failed
make: *** [obj/local/armeabi/objs/curljni/curljni.o] Error 1
I've tried many things within the Android.mk file, nothing successful. Using a PREBUILT_SHARED_LIBRARY doesn't help because it requires a .so file only and changing the extension from .so.4.2.0 to .so just tells me that the format is not supported when building ...
One thing I'm not sure about if whether I have to include the headers in my C file, but when I do it, it ofcourse don't find them.
As a note, when I build with only the curl library declared in my Android.mk file (the shared library with the C file is ommitted) then nothing is created in the libs folder !
Thanks in advance for your help !
EDIT ::::
Actually it did work mbrenon (I've tried it millions time and now it works, no idea what's different), but now I have
c:/android-ndk-r8b/toolchains/arm-linux-androideabi-4.6/prebuilt/windows/bin/../lib/gcc/arm-linux-androideabi/4.6.x-google/../../../. ./arm-linux-androideabi/bin/ld.exe: cannot find ./obj/local/armeabi/libcurl.a: Permission denied
I'm using Cygwin, could that be why I encounter permission issues ?
I manage to get around it when the .so and the .a are created, returning the permission error, chmod on it and running the ndk-build again, but that seems a bit rough !
Plus now none of my curl functions can be reached ("undefined reference to (function)").
$ ../../../ndk-build
SharedLibrary : libcurljni.so
./obj/local/armeabi/objs/curljni/curljni.o: In function `Java_test_curljni_MainActivity_stringFromJNI':
C:\android-ndk-r8b\apps\curljni\project/jni/curljni.c:12: undefined reference to `curl_easy_init'
C:\android-ndk-r8b\apps\curljni\project/jni/curljni.c:14: undefined reference to `curl_easy_setopt'
C:\android-ndk-r8b\apps\curljni\project/jni/curljni.c:15: undefined reference to `curl_easy_perform'
C:\android-ndk-r8b\apps\curljni\project/jni/curljni.c:17: undefined reference to `curl_easy_cleanup'
collect2: ld returned 1 exit status
/cygdrive/c/android-ndk-r8b/build/core/build-binary.mk:378: recipe for target `obj/local/armeabi/libcurljni.so' failed
make: *** [obj/local/armeabi/libcurljni.so] Error 1
and my curljni.c is the following
jstring Java_test_curljni_MainActivity_stringFromJNI(JNIEnv* env, jobject thiz)
{
CURL *curl;
CURLcode res;
char buffer[10];
curl = curl_easy_init();
if(curl) {
curl_easy_setopt(curl, CURLOPT_URL, "yahoo.com");
res = curl_easy_perform(curl);
curl_easy_cleanup(curl);
if(res == 0)
return (*env)->NewStringUTF(env, "0 response");
else
sprintf(buffer,"code: %i",res);
return (*env)->NewStringUTF(env, buffer);
}
else {
return (*env)->NewStringUTF(env, "no curl");
}
}
I made sure every needed function is declared in the curl.h
Yes, you do have to include the Curl headers in your C file. To allow ndk-build to find these header files at link time, you'll have to add their path using LOCAL_EXPORT_C_INCLUDES:
include $(CLEAR_VARS)
LOCAL_MODULE:= libcurl
LOCAL_SRC_FILES := libcurl.a
LOCAL_EXPORT_C_INCLUDES := /* put the path to the Curl headers here */
include $(PREBUILT_STATIC_LIBRARY)
This will automatically add the path to the headers in all the targets requiring libcurl, and it should build and link.

Categories

Resources