Errors when compiling NEON code on Android - android

Here is simple binarization function
void binarize(void *output, const void *input, int begin, int end, uint8_t threshold) {
#ifdef __ARM_NEON__
uint8x16_t thresholdVector = vdupq_n_u8(threshold);
uint8x16_t highValueVector = vdupq_n_u8(255);
uint8x16_t* __restrict inputVector = (uint8x16_t*)input;
uint8x16_t* __restrict outputVector = (uint8x16_t*)output;
for ( ; begin < end; begin += 16, ++inputVector, ++outputVector) {
*outputVector = (*inputVector > thresholdVector) & highValueVector;
}
#endif
}
It works fine on iOS. However when I'm compiling it for Android it gives me an error:
error: invalid operands of types 'uint8x16_t {aka __vector(16)
__builtin_neon_uqi}' and 'uint8x16_t {aka __vector(16) __builtin_neon_uqi}' to binary 'operator>'
I use this flag in Android.mk to enable NEON:
ifeq ($(TARGET_ARCH_ABI),armeabi-v7a)
LOCAL_ARM_NEON := true
endif

The difference comes because of different compilers. For iOS you are compiling with Clang but for Android you are building the code with GCC (unless you override the defaults).
GCC is much more stupid about vector types and could not use them with C/C++ operators like > or &. So you have two basic options:
Try to compile with Clang from the latest Android NDK r8c
Put NDK_TOOLCHAIN_VERSION=clang3.1 to your Application.mk for this.
Rewrite your code explicitly using vld1q_u8 for load, vst1q_u8 for store, vcgtq_u8 for operator > and vandq_u8 for operator &

Related

Try to set SDL with OpenGL context on Android. Get error message "Failed loading eglChooseConfig"

I am trying to run my first SDL hello-world project on android. I use the android project template provided in SDL source package, it use a class called SDLActivity to communicate with android and native c/c++ code. I import them into Eclipse android project, then slightly modify AndroidManifest.xml, Application.mk in folder jni, and Android.mk in folder jni/src .
The project compiled successfully. But when it runs on simulator (I use GenyMotion), I got error message in logcat.
E/SDLActivity(1472): Failed loading eglChooseConfig: Invalid library handle
I also try to debug on a real device. I got this message:
E/SDLActivity(28020): Failed loading eglChooseConfig: dlsym library handle is null
I tried to add "System.loadLibrary("EGL");" in SDLActivity.java . Not work.
Here is my Android.mk in jni/src
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := main
SDL_PATH := ../SDL
LOCAL_C_INCLUDES := $(LOCAL_PATH)/$(SDL_PATH)/include
# Add your application source files here...
LOCAL_SRC_FILES := $(SDL_PATH)/src/main/android/SDL_android_main.c \
main.cpp
LOCAL_SHARED_LIBRARIES :=SDL2
LOCAL_LDLIBS := -lGLESv1_CM -lGLESv2 -llog -lEGL
include $(BUILD_SHARED_LIBRARY)
I eventually found a good tutorial on youtube. I followed this video and my app works fine. I've tested my app on virtual and real devices.
Here is the sample code used by the youtube recorder. I am not the author of the code below. Just put a copy here.
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include "SDL.h"
int main(int argc, char *argv[])
{
SDL_Window* window = 0;
SDL_GLContext gl = 0;
if(0 != SDL_Init(SDL_INIT_VIDEO))
{
fprintf(stderr,"Unable to initialize SDL: %s\n",SDL_GetError());
return 1;
}
SDL_LogSetAllPriority(SDL_LOG_PRIORITY_VERBOSE);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION,2);
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER,1);
SDL_DisplayMode mode;
SDL_GetDisplayMode(0,0,&mode);
int width = mode.w;
int height = mode.h;
SDL_Log("Width = %d, Heigh = %d. \n",width,height);
SDL_GL_SetAttribute(SDL_GL_ACCELERATED_VISUAL,1);
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER,1);
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE,24);
window = SDL_CreateWindow(NULL,0,0,width,height,SDL_WINDOW_OPENGL | SDL_WINDOW_FULLSCREEN | SDL_WINDOW_RESIZABLE);
if(window == 0)
{
SDL_Log("Failed to create window.");
SDL_Quit();
return 1;
}
//Create an opengl context
gl = SDL_GL_CreateContext(window);
/*Main Render Loop*/
Uint8 done = 0;
SDL_Event event;
int count = 0;
while(!done)
{
/*Check for events*/
while(SDL_PollEvent(&event))
{
if(event.type == SDL_QUIT || event.type == SDL_KEYDOWN || event.type == SDL_FINGERDOWN)
{
done = 1;
}
}
SDL_Log("%d\n",count++);
SDL_GL_SwapWindow(window);
SDL_Delay(10);
}
exit(0);
}
This code will let you know how to initialize SDL on android. There is one thing needs to take care of: version of openGL ES needs to set correctly. For example, I use openGLES 1.1, so I change
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION,2);
to
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION,1);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION,1);

Android - NDK strange error

I start getting funny errors with NDK with fairly complex program:
#include <stdio.h>
#include <iostream>
int main( int argc, char **argv ) {
return 0;
}
>call c:\android-ndk-r9\ndk-build.cmd
"Compile++ thumb : test <= test.cpp
In file included from C:/workspace/c++11_test//jni/test.cpp:11:
In file included from c:/android-ndk-r9/sources/cxx-stl/stlport/stlport\iostream:43:
In file included from c:/android-ndk-r9/sources/cxx-stl/stlport/stlport\stl/_istream.h:31:
In file included from c:/android-ndk-r9/sources/cxx-stl/stlport/stlport\stl/_ostream.h:380:
In file included from c:/android-ndk-r9/sources/cxx-stl/stlport/stlport\stl/_ostream.c:26:
In file included from c:/android-ndk-r9/sources/cxx-stl/stlport/stlport\stl/_num_put.h:180:
In file included from c:/android-ndk-r9/sources/cxx-stl/stlport/stlport\stl/_num_put.c:26:
c:/android-ndk-r9/sources/cxx-stl/stlport/stlport\stl/_limits.h:217:48: error: non-type template argument evaluates to -2147483648, which cannot be narrowed to type 'wchar_t'
[-Wc++11-narrowing]
: public _STLP_PRIV _Integer_limits<wchar_t, WCHAR_MIN, WCHAR_MAX, -1, true>
^
c:/android-ndk-r9/platforms/android-14/arch-arm/usr/include\../include/wchar.h:76:22: note: expanded from macro 'WCHAR_MIN'
#define WCHAR_MIN INT_MIN
^
c:/android-ndk-r9/platforms/android-14/arch-arm/usr/include\sys/limits.h:69:18: note: expanded from macro 'INT_MIN'
#define INT_MIN (-0x7fffffff-1) /* min value for an int */
^
1 error generated.
make: * [C:/workspace/c++11_test//obj/local/armeabi/objs/test/test.o] Error 1
It's ndk-r9. 4.8 complie it just fine, only clang stumbles on it.
Do I need to define something to make clang work?
I've tried to Google errors, but got nothing relevant...
Obviously, I can turn it off with -Wno-c++11-narrowing, but I don't want disable narrowing checks.
And it's only shows with stlport_static, there is NO error with gnustl_static
You appear to have enabled C++11, since you are getting this warning.
STLport support for C++11 is not very good. I suspect this is the reason for your woes.
A fix requires changes to STLport, or removing the "-std=c++11" switch from the clang command-line.
IMHO, I would recommend switching to the gnustl (aka. libstdc++), unless there are other reasons that prevent you from doing so (licensing: libstdc++ is GPL3 with some significant exceptions that may or may not be valid for clang - you should determine that for yourself), legacy support, size etc.). I have had very good experiences with that.

C++11 std::async in Android NDK does not work

I have tried to get following sample code working to know whether asynchronous programming is working in Android NDK. Though NDK has the STL <future> which gets recognized as a header, the std::async is not getting recognized are not getting recognized. The code I tried to use was the following:
#include <future>
#include <iostream>
struct Foo
{
Foo() : data(0) {}
void sum(int i) { data +=i;}
int data;
};
int main()
{
Foo foo;
auto f = std::async(&Foo::sum, &foo, 42);
f.get();
std::cout << foo.data << "\n";
}
Also all the include paths have been set to the specified folder under Properties->Paths and Symbols
Errors
Description Resource Path Location Type
invalid use of incomplete type 'std::__async_sfinae_helper<void (Foo::*)(int), void (Foo::*)(int), Foo*, int>::type {aka struct std::future<void>}' Sample.cpp /Project12/jni line 50 C/C++ Problem
Description Resource Path Location Type
declaration of 'std::__async_sfinae_helper<void (Foo::*)(int), void (Foo::*)(int), Foo*, int>::type {aka struct std::future<void>}' Project12 line 111, external location: D:\android-ndk-r8e-windows-x86_64\android-ndk-r8e\sources\cxx-stl\gnu-libstdc++\4.6\include\future C/C++ Problem
Curently Android NDK does not incorporate all of the C++11 features. Clang 3.3 compiler from NDK r9b is C++11-feature complete, however, STL and stdlib on Android are not.
To use the most recent C++11 feature set in Android use Clang 3.3 compiler from Android NDK r9b. Put this line into your Application.mk file:
NDK_TOOLCHAIN_VERSION := clang
Also, add -std=c++11 switch to the LOCAL_CPPFLAGS variable:
LOCAL_CPPFLAGS += -std=c++11

Latest C++11 features with Android NDK

I am trying to use C++11 threading facilities with Android NDK, but not sure how to make it use the latest compilers.
I have Clang 3.2 and can build iOS apps. I wonder if there is a way to do it with Android NDK?
If not, then how should I build with gcc 4.8?
(I'm addressing the NDK version r9b)
To enable C++11 support for all source code of the application (and so any modules included) make the following change in the Application.mk:
# use this to select gcc instead of clang
NDK_TOOLCHAIN_VERSION := 4.8
# OR use this to select the latest clang version:
NDK_TOOLCHAIN_VERSION := clang
# then enable c++11 extentions in source code
APP_CPPFLAGS += -std=c++11
# or use APP_CPPFLAGS := -std=gnu++11
Otherwise, if you wish to have C++11 support only in your module, add this lines into your Android.mk instead of use APP_CPPFLAGS
LOCAL_CPPFLAGS += -std=c++11
Read more here:
http://adec.altervista.org/blog/ndk_c11_support/
NDK revision 10 has the Clang 3.6 toolchain. Use it:
NDK_TOOLCHAIN_VERSION := clang3.6
or use the latest available Clang toolchain
NDK_TOOLCHAIN_VERSION := clang
NDK revision 8e has the Clang 3.2 compiler bundled in it. Use it and you're good to go.
First, to decide which toolchain to use, edit your "application.mk" (do not confuse with android.mk) and insert for gcc 4.8:
NDK_TOOLCHAIN_VERSION := 4.8
or if you want clang:
NDK_TOOLCHAIN_VERSION := clang
But this has nothing to do with threads. This will only define which toolchain to use.
Now about threads, here is a simple example for android NDK:
#include <pthread.h> // <--- IMPORTANT
// This will be used to pass some data to the new thread, modify as required
struct thread_data_arguments
{
int value_a
bool value_b;
};
//---------------------------------
// This function will be executed in the new thread, do not forget to put * at the start of the function name declaration
void *functionRunningInSeparateThread(void *arguments)
{
struct thread_data_arguments *some_thread_arguments = (struct thread_data_arguments*)arguments;
if (some_thread_arguments->value_b == true)
{
printf("VALUE= %i", some_thread_arguments->value_a);
}
// Signal the end of the thread execution
pthread_exit(0);
}
//---------------------------------
// This is the actual function creating and starting the new thread
void startThread()
{
// Lets pass some data to the new thread, you can pass anything even large data,
// for that you only need to modify thread_data_arguments as required
struct thread_data_arguments *some_thread_arguments;
some_thread_arguments = (thread_data_arguments*)malloc(sizeof(*some_thread_arguments));
some_thread_arguments->value_a = 12345;
some_thread_arguments->value_b = true;
// Create and start the new thread
pthread_create(&native_thread, NULL, functionRunningInSeparateThread, (void*)some_thread_arguments)
}
For ndk builds, open Application.mk and add following info. in it (if using r8e):
NDK_TOOLCHAIN_VERSION=4.7
Note: Please use 4.8 in case you are using NDK revision 9.
Note that Android gcc support is now deprecated. You should now be using clang. Please read the version 11 release notes. You can specify:
NDK_TOOLCHAIN_VERSION=clang
To use the latest version based on your installed NDK. Also---as of this writing---the latest NDK (v12) is only accessable via Android Studio, and not through either the Downloads page or Standalone SDK Manager.

Build Android-openssl library for platform 2.1

I am using open-ssl source given at https://github.com/eighthave/openssl-android
to build a library which can be used in android project.
As per instructions given at README.txt, I am able to compile it for the the Android platform version 2.2 (level -8)
But my app requires it to be 2.1 (level -7) compatible.
I tried following options with the default.properties file ( https://github.com/eighthave/openssl-android/blob/master/default.properties )
1) set target=android-7
2) set target=android-5
But when I compile it using command ndk-build, it gives following error
Compile thumb : crypto <= dsa_vrf.c
Compile thumb : crypto <= dso_dl.c
Compile thumb : crypto <= dso_dlfcn.c
/Crypto/openssl-android/crypto/dso/dso_dlfcn.c: In function 'dlfcn_pathbyaddr':
/Crypto/openssl-android/crypto/dso/dso_dlfcn.c:445: error: 'Dl_info' undeclared (first use in this function)
/Crypto/openssl-android/crypto/dso/dso_dlfcn.c:445: error: (Each undeclared identifier is reported only once
/Crypto/openssl-android/crypto/dso/dso_dlfcn.c:445: error: for each function it appears in.)
/Crypto/openssl-android/crypto/dso/dso_dlfcn.c:445: error: expected ';' before 'dli'
/Crypto/openssl-android/crypto/dso/dso_dlfcn.c:455: error: 'dli' undeclared (first use in this function)
make: *** [obj/local/armeabi/objs/crypto/dso/dso_dlfcn.o] Error 1
As per error message- Dl_info is not defined. but if we go to file dso_dlfcn.c , the definition for the structure is already provided. (https://github.com/eighthave/openssl-android/blob/master/crypto/dso/dso_dlfcn.c)
And this code compiled for target=android-8 in default properties file, but not for android-7 or android-5.
Request you to help me to resolve this error. and let me know what all changes needs to be done in order to compile it for android 2.1 platform.
Thanks in advance.
Try to include the following piece of code into dso_dlfcn.c:
typedef struct {
const char *dli_fname; /* Pathname of shared object that
contains address */
void *dli_fbase; /* Address at which shared object
is loaded */
const char *dli_sname; /* Name of nearest symbol with address
lower than addr */
void *dli_saddr; /* Exact address of symbol named
in dli_sname */
} Dl_info;
int dladdr(const void *addr, Dl_info *info) { return 0; }
Before:
#ifdef __linux
# ifndef _GNU_SOURCE
# define _GNU_SOURCE /* make sure dladdr is declared */
# endif
#endif
After that in my case the library is built.
Try to install with latest NDK version and update Application.mk file appropriately.
LOCAL_PATH := $(call my-dir)
APP_PLATFORM := android-19
NDK_TOOLCHAIN_VERSION := clang
APP_ABI := armeabi-v7a
APP_STL := gnustl_static
APP_CPPFLAGS += -frtti
APP_CPPFLAGS += -fexceptions
APP_CPPFLAGS += -DANDROID
APP_PROJECT_PATH := $(shell pwd)
APP_BUILD_SCRIPT := $(LOCAL_PATH)/../Android.mk
The above 2 problems will be solved.
I had one issue with #Yuri's solution and had to improve it alittle. My APP_ABI is set to all in Application.mk. In my case it meant that among armeabi and armeabi-v7a I'm building also for x86 and mips. I have also android-9 target installed in android sdk to use in other projects. x86 and mips are supported by ndk starting from android-9. As written in the docs, when ndk-build will start building these targets, it will switch to android-9 target automatically. And what? - Yes, it will fail to compile :-). Here is my solution:
In crypto/Android.mk find the line local_c_flags :=
-DNO_WINDOWS_BRAINDEATH. After the line write this http://pastebin.com/7euUVD7A.
Yuri's code has to be inserted into if defined: http://pastebin.com/V58gTSBU
By the way, I've inserted Yuri's block after #include <openssl/dso.h> but not before #ifdef __linux

Categories

Resources