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.
Related
Trying to print to console when running my Flutter app (on Android) from the following C++ code I am running through dart:ffi:
#include <iostream>
std::cout << "Hello, World!";
Does not give me any output in the terminal. How would I print to the Flutter terminal from C++?
I know my functions otherwise work correctly because I am getting correct actions on pointers / return values.
Edit: When only running on android, there is a simpler way. I have updated the answer below.
You'll have to pass a wrapper to the print function into the native code
void wrappedPrint(Pointer<Utf8> arg){
print(Utf8.fromUtf8(arg));
}
typedef _wrappedPrint_C = Void Function(Pointer<Utf8> a);
final wrappedPrintPointer = Pointer.fromFunction<_wrappedPrint_C>(_wrappedPrint_C);
final void Function(Pointer) initialize =
_nativeLibrary
.lookup<NativeFunction<Void Function(Pointer)>>("initialize")
.asFunction<void Function(Pointer)>();
initialize(wrappedPrintPointer);
and then use that in your C library:
void (*print)(char *);
void initialize(void (*printCallback)(char *)) {
print = printCallback;
print("C library initialized");
}
void someOtherFunction() {
print("Hello World");
}
When only running on android, things get simpler. Instead of all of the above, do:
Simply use the android logging mechanism, it will show up on the console, at least when using flutter run. I'm assuming flutter attaches to logcat using the app's PID.
To do so, update the CMakeLists.txt with:
find_library( # Defines the name of the path variable that stores the
# location of the NDK library.
log-lib
# Specifies the name of the NDK library that
# CMake needs to locate.
log )
# Links your native library against one or more other native libraries.
target_link_libraries( # Specifies the target library.
<your-libs-name-here>
# Links the log library to the target library.
${log-lib} )
and in your c lib do:
#include <android/log.h>
void someOtherFunction() {
__android_log_print(ANDROID_LOG_DEBUG, "flutter", "Hello world! You can use %s", "formatting");
}
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.
On Android NDK project we need to access bluetooth using a HAL interface. Our intention is to do something like this:
#include <hardware/hardware.h>
#include <hardware/bluetooth.h>
....
void load_Module(....)
{
hw_module_t* module;
hw_device_t* device;
bdt_log("Loading HAL lib + extensions");
err = hw_get_module(BT_HARDWARE_MODULE_ID, (hw_module_t const**)&module);
if (err == 0){
err = module->methods->open(module, BT_HARDWARE_MODULE_ID, &device);
if (err == 0) {
bt_device = (bluetooth_device_t *)device;
sBtInterface = bt_device->get_bluetooth_interface();
}
}
}
Everybody seems to do the same (in google example code). There appears to be a problem when we try to compile:
#include <hardware/hardware.h> no such file
We properly added a permission to manifest and properly added libraries at Android.mk
Do we need to add something more? Is there a working project that I can refer to?
You're trying to use libhardware on Android NDK project. libhardware is a part of Android framework, not a part of NDK.
https://github.com/android/platform_hardware_libhardware
So your project doesn't have true binary compatibility of Android if you can build your project with libhardware. It would work on some devices, some versions, but no guarantee.
From my experience, I believe you can build your code on AOSP. You need to modify Android.mk for AOSP not NDK.
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.