I'm building a jni lib for android using NDK, I need to change pipe buffer size, but fcntl(pipe_fd[0], F_SETPIPE_SZ, 1048576);
compiling failed, errror message "F_SETPIPE_SZ undelcard", I already added #define _GNU_SOURCE at the beginning of the C++ source file. What could be the reason?
I'm guessing your problem is that you never ended your #ifndef for _GNU_SOURCE, since you state that you have included it at the beginning. Here is an example of what your files should look like that need access to that macro:
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#include <fcntl.h>
extern "C"
{
int test()
{
int some_fd = 123456;
int size_in_bytes = 12345;
return fcntl(some_fd, F_SETPIPE_SZ, 12345);
}
} // End extern
#endif
Checked against the following versions
Android Studio: 1.3.2
NDK: r10e
Various gradle settings:
compileSdkVersion 22
buildToolsVersion "23.0.0 rc3"
Related
I am trying to build my android application with support for OpenSceneGraph. I am trying to render a simple box from my project's raw folder. However, when I build the project I am getting this compile error in the FileUtils class of the OpenSceneGraph library:
Class 'stat64' doesn't have constructor stat64(const char *,stat64*)
Any ideas what is causing the problem?
I'm also faced with such problem when I have tried to compile OpenSceneGraph to Android. The problem is that NDK's <sys/stat.h> header for Android API less that 21 doesn't contain stat64 function definition so compiler thinks that stat64 is a struct. Problem can be solved by adding
#if defined(ANDROID) || defined(__ANDROID__)
#if __ANDROID_API__ < 21
#define stat64 stat
#endif
#endif
after src/osgDB/FileUtils.cpp:92.
I am using __system_property_get() from sys/system_properties.h to get a system property. I am trying to use r10c ndk because I need arm64 toolchain.
__system_property_get() is defined in libc.so. Below is the readelf output of libc.so for armv5/armv7a.
readelf -Ws libc.so | grep property_get
194: 00009100 20 FUNC GLOBAL DEFAULT 4 __system_property_get
198: 00009100 20 FUNC GLOBAL DEFAULT 4 __system_property_get
But, looks like it has been removed for arm64 version! I am getting a linker error saying it is not defined. I analyzed all the shared libraries of arm64 but none of them have that symbol.
Is there an alternate API to get the system property in the native code?
Thank you!
It's useful API for native apps, just as it is for Java apps, it originates from the native side (see http://rxwen.blogspot.com/2010/01/android-property-system.html), and other Android system code uses it, so it's unlikely to go away soon.
#include <android/log.h>
#include <dlfcn.h>
#if (__ANDROID_API__ >= 21)
// Android 'L' makes __system_property_get a non-global symbol.
// Here we provide a stub which loads the symbol from libc via dlsym.
typedef int (*PFN_SYSTEM_PROP_GET)(const char *, char *);
int __system_property_get(const char* name, char* value)
{
static PFN_SYSTEM_PROP_GET __real_system_property_get = NULL;
if (!__real_system_property_get) {
// libc.so should already be open, get a handle to it.
void *handle = dlopen("libc.so", RTLD_NOLOAD);
if (!handle) {
__android_log_print(ANDROID_LOG_ERROR, "foobar", "Cannot dlopen libc.so: %s.\n", dlerror());
} else {
__real_system_property_get = (PFN_SYSTEM_PROP_GET)dlsym(handle, "__system_property_get");
}
if (!__real_system_property_get) {
__android_log_print(ANDROID_LOG_ERROR, "foobar", "Cannot resolve __system_property_get(): %s.\n", dlerror());
}
}
if (!__real_system_property_get) return (0);
return (*__real_system_property_get)(name, value);
}
#endif // __ANDROID_API__ >= 21
In older NDKs this was not an officially supported API. It was mistakenly exposed to the 32-bit ABIs early on, but wasn't exposed to the 64-bit ABIs until it was officially supported. Regardless, it is exposed by the system at all API levels, so newer NDKs are able to use this regardless of ABI or minSdkVersion.
Confirming #bleater's answer as a workaround for the unexposed __system_properties_* symbols: dlopen libc and dlsym as needed.
I am very much new to cocos2dx. I have a cocos2dx project made in xcode. for gesture recognizers I used cocoa touch's native code(UIGestureRecognizers) in cocos2dx using .mm files.
Now I want to build this project with android sdk too.
The Error i am getting by building the android project using build_native.sh file, in terminal is Like The Following
1
../android-ndk-r9d/toolchains/arm-linux-androideabi-4.6/prebuilt/darwin-x86_64/bin/../lib/gcc/arm-linux-androideabi/4.6/../../../../arm-linux-androideabi/bin/ld: ./obj/local/armeabi/objs/cocos2dcpp_shared/__/__/Classes/HelloWorldScene.o: in function HelloWorld::menuCloseCallback(cocos2d::CCObject*):jni/../../Classes/HelloWorldScene.cpp:88: error: undefined reference to 'XBridge::doSth()'
2
../android-ndk-r9d/toolchains/arm-linux-androideabi-4.6/prebuilt/darwin-x86_64/bin/../lib/gcc/arm-linux-androideabi/4.6/../../../../arm-linux-androideabi/bin/ld: ./obj/local/armeabi/objs/cocos2dcpp_shared/__/__/Classes/HelloWorldScene.o: in function HelloWorld::menuCloseCallback(cocos2d::CCObject*):jni/../../Classes/HelloWorldScene.cpp:85: error: undefined reference to 'XBridge::imageName'
collect2: ld returned 1 exit status
make: *** [obj/local/armeabi/libcocos2dcpp.so] Error 1
make: Leaving directory `../cocos2d-x/projects/MyGame/proj.android'
What Am I missing Here ? I just started learning cocos2dx.
Can i even use the native iOS code like this in an android project ? or i am just shooting blanks ?
My Code is as written below.
CODE IN MY HelloWorldScene.cpp
void HelloWorld::menuCloseCallback(CCObject* pSender)
{
#if (CC_TARGET_PLATFORM == CC_PLATFORM_WINRT) || (CC_TARGET_PLATFORM == CC_PLATFORM_WP8)
CCMessageBox("You pressed the close button. Windows Store Apps do not implement a close button.","Alert");
#else
cocos2d::CCString * imageNameString = cocos2d::CCString::create("image.png");
XBridge::imageName = imageNameString->getCString();
XBridge::doSth();
#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
//exit(0);
#endif
#endif
}
Code In XBridge.h
#ifndef xbridge_XBridgeViewController_h
#define xbridge_XBridgeViewController_h
#include "cocos2d.h"
class XBridge {
public:
static std::string imageName;
static void doSth();
};
#endif
Code In XBridge.mm
#include "XBridge.h"
#include "AppController.h"
#include "RootViewController.h"
#include "SpriteVC.h"
using namespace cocos2d;
std::string XBridge::imageName;
void XBridge::doSth()
{
id sth = [[UIApplication sharedApplication] delegate];
if ([sth isKindOfClass:[AppController class]])
{
printf("XBridge::doSth imageName %s\n",imageName.c_str());
SpriteVC *SPVC = [[SpriteVC alloc] initWithNibName:nil bundle:nil];
SPVC.imageNameString = [NSString stringWithFormat:#"%s",imageName.c_str()];
[SPVC setUpImage];
NSLog(#"XBridge::doSth imageName == %#",[NSString stringWithFormat:#"%s",imageName.c_str()]);
//SPVC.imageView.frame = CGRectMake(480, 320, 333, 333);
AppController *controller = (AppController *)sth;
[controller.viewController.view addSubview:SPVC.photoImage];
}
}
You can't use iOS Cocoa Touch API for Android even though you actually can compile Objective-C and Objective-C++ code using Android NDK Clang toolchain. Because Android NDK doesn't provide iOS API at all like UIApplication, AppController, and so forth. Cocos2d-x just provides Cocos2d-x API in C++ and some plugins for Android.
If you want to use iOS API for Android, take a look at Apportable.
I am trying to port the following piece of C++ code to Android as part of some NDK work:
#include <fstream>
// ...
inline void trim(string & str, const string & delim = " \t\r\n")
{
string::size_type pos = str.find_last_not_of(delim);
if(pos == string::npos) str.erase(str.begin(), str.end());
else
{
str.erase(pos+1);
pos = str.find_first_not_of(delim);
if(pos != string::npos) str.erase(0, pos);
}
}
What I get is the following message at str.erase(pos+1); and str.erase(0, pos):
Invalid arguments '
Candidates are:
std::basic_string<char,std::char_traits<char>,std::allocator<char>> & erase(?, ?)
__gnu_cxx::__normal_iterator<char *,std::basic_string<char,std::char_traits<char>,std::allocator<char>>> erase(__gnu_cxx::__normal_iterator<char *,std::basic_string<char,std::char_traits<char>,std::allocator<char>>>)
__gnu_cxx::__normal_iterator<char *,std::basic_string<char,std::char_traits<char>,std::allocator<char>>> erase(__gnu_cxx::__normal_iterator<char *,std::basic_string<char,std::char_traits<char>,std::allocator<char>>>, __gnu_cxx::__normal_iterator<char *,std::basic_string<char,std::char_traits<char>,std::allocator<char>>>)
'
I tried what was suggested here but it did not help. Instead, now I am getting a new message for #include <fstream>:
Unresolved inclusion: <fstream>
What do I need to do to resolve this? Thank you.
UPDATE: I am trying to add this piece of code to an existing C++ code in an Android project that built and ran fine. When I applied the change linked to above, I not only got the unresolved inclusion for fstream, I also got a bunch of other errors. For instance, for the following block form the existing code:
#include <jni.h>
#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/features2d/features2d.hpp>
#include <vector>
I am also getting Unresolved inclusion errors. So it made things worse.
Try to add the following line to Application.mk of your project.
APP_STL := gnustl_static
I have a simple file stlTest2.cpp like this:
#include <jni.h>
#include <cmath>
bool isnan (void);
There is something more complicated in some code I am porting. My question is this. Why would this work when building using GCC outside of the NDK, but not with using the NDK? There error it gives is this:
jni/stlTest2.cpp:6: error: expected unqualified-id before 'sizeof'
jni/stlTest2.cpp:6: error: expected ')' before 'sizeof'
The immediate reason for this is that math.h (included via <cmath>) defines isnan as a macro. Why is the build outside of the ndk not including the #define from math.h, but this is? If I comment out the includes in the code, all is fine, but that is not acceptable as this problem repeats itself.... a lot.
The isnan macro was added in C99. In C++11 it was added as a function in the std namespace, overloaded for float and double and long double (so a typical <cmath> header, such as your non-NDK GCC is probably using, might have something like this:
#undef isnan
inline bool isnan(float ...) { ... }
inline bool isnan(double ...) { ... }
inline bool isnan(long double ...) { ... }
), but apparently the NDK hasn't gotten the memo, and is still providing the C99 macro as a convenience. (isnan was never a macro in C++, but before TR1 added std::tr1::isnan, there wasn't really a C++ alternative, so multiple C++ compilers provided the C99 macro.)
Do you need to be able to use the compiler-provided isnan or std::isnan? If not, then you can just change this:
#include <cmath>
to this:
#include <cmath>
#undef isnan
(and similarly for any other problematic macros, provided you don't need them).
In $ndk\sources\cxx-stl\gnu-libstdc++\libs\armeabi\include\bits\c++config.h (change armeabi to whatever is appropriate) change this:
/* #undef _GLIBCXX_USE_C99_MATH */
to
#define _GLIBCXX_USE_C99_MATH 1
Then clean and build your project again.