First off, my app has a file named Android.hpp. This is part of the tmxlite library. Compiling tmxlite on windows works fine. However, when I move the code to android studio and compile it (with the NDK), I get an error.
Android.hpp:
/*********************************************************************
Matt Marchant 2016
http://trederia.blogspot.com
tmxlite - Zlib license.
This software is provided 'as-is', without any express or
implied warranty. In no event will the authors be held
liable for any damages arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute
it freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented;
you must not claim that you wrote the original software.
If you use this software in a product, an acknowledgment
in the product documentation would be appreciated but
is not required.
2. Altered source versions must be plainly marked as such,
and must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any
source distribution.
*********************************************************************/
#ifndef ANDROID_INC_HPP_
#define ANDROID_INC_HPP_
#ifdef __ANDROID__
#include <string>
#include <sstream>
#include <cstdlib>
namespace std
{
template <typename T>
std::string to_string(T value)
{
std::ostringstream os;
os << value;
return os.str();
}
}
#define STOI(str) std::strtol(str.c_str(), 0, 10)
#else
#define STOI(str) std::stoi(str)
#endif // __ANDROID__
#endif // ANDROID_INC_HPP_
The error:
In file included from E:\max\android_libs\tmxliteOG\tmxlite\src\FreeFuncs.cpp:28:
In file included from E:\max\android_libs\tmxliteOG\tmxlite\include\tmxlite\FreeFuncs.hpp:54:
E:\max\android_libs\tmxliteOG\tmxlite\include\tmxlite\detail\Android.hpp:37:11: error: expected '{'
Why is this happening? I was under the impression that this was how namespaces were supposed to be declared and I don't see what is wrong with it. I mean, I didn't even write the code :-).
help is greatly appreciated.
Related
I compiled the gRPC Android example from here.
I want to run the program as executable from adb shell.
Added these lines to grpc-helloworld.cc:
#include <iostream>
int main() {
std::cout << "qwerty" << std::endl;
return 0;
}
And these lines to its CMakeLists.txt:
add_executable(avocado
src/main/cpp/grpc-helloworld.cc)
target_include_directories(avocado
PRIVATE ${HELLOWORLD_PROTO_HEADERS})
target_link_libraries(avocado
helloworld_proto_lib
android
${log-lib})
Then I pushed the generated executable and libs file and tried to run it:
LD_LIBRARY_PATH=. ./avocado
I got the following error:
[libprotobuf FATAL
/home/buga/grpc/third_party/protobuf/src/google/protobuf/stubs/common.cc:79]
This program was compiled against version 3.0.0 of the Protocol Buffer
runtime library, which is not compatible with the installed version
(3.5.1). Contact the program author for an update. If you compiled
the program yourself, make sure that your headers are from the same
version of Protocol Buffers as your link-time library. (Version
verification failed in
"out/soong/.intermediates/frameworks/av/drm/libmediadrm/libmediadrm/android_arm64_armv8-a_kryo300_shared_core/gen/proto/frameworks/av/drm/libmediadrm/protos/plugin_metrics.pb.cc".)terminating
with uncaught exception of type google::protobuf::FatalException: This
program was compiled against version 3.0.0 of the Protocol Buffer
runtime library, which is not compatible with the installed version
(3.5.1). Contact the program author for an update. If you compiled
the program yourself, make sure that your headers are from the same
version of Protocol Buffers as your link-time library. (Version
verification failed in
"out/soong/.intermediates/frameworks/av/drm/libmediadrm/libmediadrm/android_arm64_armv8-a_kryo300_shared_core/gen/proto/frameworks/av/drm/libmediadrm/protos/plugin_metrics.pb.cc".)
Aborted
What am I doing wrong?
We realized that there is a version of the protobuf library called libprotobuf-cpp-full.so and libprotobuf-cpp-lite.so, and it seems that their version is 3.0.0. This is conflicting with our version (3.5.1) which is compiled into either a static lib, or as a shared lib.
I'm not quite sure why this happens. Something about once the linker loads helloworld_proto_lib, it overrides all loaded protobuf symbols, and for some reason another library that you had nothing to do with crashes your program. But that's not telling you anything new.
Here's one way to solve this problem:
1. Changes to grpc-helloworld.cc
Make the main extern "C", and change its name maybe. For example:
extern "C" int my_main() {
std::cout << "qwerty" << std::endl;
return 0;
}
2. Add file grpc-avocado.cc
This will contain the actual main of the executable, which will dynamically load the libraries helloworld_proto_lib and grpc-helloworld. Here's how to do it:
#include <iostream>
#include <android/dlext.h>
#include <dlfcn.h>
int main() {
android_dlextinfo extinfo;
extinfo.flags = ANDROID_DLEXT_FORCE_LOAD;
void* proto_lib = android_dlopen_ext("/path/to/libhelloworld_proto_lib.so", RTLD_LAZY, &extinfo);
void* helloworld = dlopen("/path/to/libgrpc-helloworld.so", RTLD_LAZY);
int (*my_main)() = (int (*)())dlsym(helloworld, "my_main");
return my_main();
}
The function android_dlopen_ext from #include <android/dlext.h>, and its flag argument, are described here: https://developer.android.com/ndk/reference/group/libdl . In the above code we pass the flag ANDROID_DLEXT_FORCE_LOAD, which is documented as:
When set, do not use stat(2) to check if the library has already been loaded.
This flag allows forced loading of the library in the case when for some reason multiple ELF files share the same filename (because the already-loaded library has been removed and overwritten, for example).
Note that if the library has the same DT_SONAME as an old one and some other library has the soname in its DT_NEEDED list, the first one will be used to resolve any dependencies.
I think the text in bold is what explains why this solution works.
3. Change CMakeLists.txt
Since you'll be loading helloworld_proto_lib dynamically, you can now remove it from the executable definition, and there's no need for any proto headers:
add_executable(avocado
src/main/cpp/grpc-avocado.cc)
target_link_libraries(avocado
android
${log-lib})
Build, push, and run
You can now build, push the executable avocado and the two libraries libgrpc-helloworld.so, libhelloworld_proto_lib.so, and run. You don't need LD_LIBRARY_PATH. Good luck with the rest of your project!
Im trying to build an Ubuntu Touch tree, based on an Aosp tree I already correctly built.
It fails with this error
CAPEWrapper.cpp:16: error: undefined reference to '__xlog_buf_printf'
this is the header that file includes
#include "CAPEWrapper.h"
which on cascade includes
#include <cutils/xlog.h>
which in turn defines
#if defined(__cplusplus)
extern "C" {
#endif
int __xlog_buf_printf(int bufid, const struct xlog_record *rec, ...);
#if defined(__cplusplus)
}
#endif
I suspect that my g++ doesn't set __cplusplus macro. Could it be a realistic scenario with this kind of error? If this could be the problem, should I need to specify a standard implementation with "stdc=something" to solve it?
Any other idea is welcome.
Make sure that your project is linking libcutils, and that it's linking it in the correct order (i.e. that -lcutils appears in the linker command line after any module that depends on it).
In the end, I found that the modules was listed inside a macro called LOCAL_WHOLE_STATIC_LIBRARIES, that in Android environment passes its content to the --whole-archive flag of GCC linker.
I'm familiar with Android kernel programming but I'm a newbie at building the Android source. I'm wondering how to enable the #ifdefs in android source building. Are there any defconfig file in android source like in android kernel to choose what we want to compile in the compilation?.. How can i enable the codings defined with #ifdef to get compile during the Android source compilation?
Ex:
#ifdef USE_ION
int alloc_map_ion_memory(OMX_U32 buffer_size,
OMX_U32 alignment, struct ion_allocation_data *alloc_data,
struct ion_fd_data *fd_data,int flag);
void free_ion_memory(struct vdec_ion *buf_ion_info);
#else
bool align_pmem_buffers(int pmem_fd, OMX_U32 buffer_size,
OMX_U32 alignment);
#endif
I want to make sure the ion part is being compiled not the pmem part.
Try add the line:
#error "USE_ION"
after #ifdef USE_ION
Build again, if the build failed, USE_ION is defined.
today I faced trouble - android's ndk does not have SUN_LEN macro (sys/un.h || linux/un.h ), I don't want to patch android's headers, what is better to do?
Don't patch the headers, define it in your own file.
#ifndef SUN_LEN //In case they fix it down the road
#define SUN_LEN(ptr) ((size_t) (((struct sockaddr_un *) 0)->sun_path) + strlen((ptr)->sun_path))
#endif
SUN_LEN macro is a non-portable (aka not a part of POSIX standard) extension.
It is completely safe to use sizeof(struct sockaddr_un) instead.
While working with some sources written in C++ I found those macro:
JNIEXPORT return_type JNICALL function_name(...) {
However, Android NDK samples don't use them. I read some docs from Oracle, but I'm still confused.
Do I necessarily have to use them while working with Android NDK?
One of the reasons for asking - those macro break syntax highlighting in eclipse CDT :)
Basically is a windows issue, if you have a look to the file jni_md_win32.h that comes with oracle Java jdk this is the macro definition:
/*
* #(#)jni_md.h 1.14 03/12/19
*
* Copyright 2004 Sun Microsystems, Inc. All rights reserved.
* SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*/
#ifndef _JAVASOFT_JNI_MD_H_
#define _JAVASOFT_JNI_MD_H_
#define JNIEXPORT __declspec(dllexport)
#define JNIIMPORT __declspec(dllimport)
#define JNICALL __stdcall
typedef long jint;
typedef __int64 jlong;
typedef signed char jbyte;
#endif /* !_JAVASOFT_JNI_MD_H_ */
In the header jni_md_linux.h those macros are empty. So I guess that as long you don't want your native code to be executed in windows with oracle JVM you can remove those macros.
Check that the include path of the platform you desire from the Android NDK has been added to your project's C\C++ includes. This can be done as follows:
Open the project properties
Expand C/C++ General
Click Paths and Symbols
In the Includes section Add the path to the includes folder of the desired platform of the NDK (e.g. ${ANDROID_NDK_HOME}\platforms\android-9\arch-arm\usr\include )