I've long forgotten c++ and how to use it properly, but now I have to deal with one class and I'm a little bit stuck. So I'm using cocos2dx to write a game for ios, however I am using Lua bindings instead of c++. But... even though, I need to write something that uses JNI so... c/c++ here we come.
I've got the header file and cpp file like this:
DeviceInfoAndroid.h:
#include <jni.h>
#include "../libs/cocos2dx/platform/android/jni/JniHelper.h"
extern "C" {
const char* getAndroidDeviceId();
}
DeviceInfoAndroid.cpp:
#ifndef _DEVICE_INFO_ANDROID_
#define _DEVICE_INFO_ANDROID_
#include "DeviceInfoAndroid.h"
#include <string>
extern "C" {
const char *getAndroidDeviceId() {
JniMethodInfo t;
const char* retVal;
if (JniHelper::getStaticMethodInfo(t
, "org/cocos2dx/lib/Cocos2dxActivity" //org/cocos2dx/lib/Cocos2dxActivity
, "getIMEI"
, "()Ljava/lang/String;")) {
jstring jstr;
jstr = (jstring);
t.env->CallStaticObjectMethod(t.classID, t.methodID);
char *cstr;
cstr = (char *) t.env->GetStringUTFChars(jstr, 0);
std::string ret(cstr);
t.env->ReleaseStringUTFChars(jstr, cstr);
t.env->DeleteLocalRef(jstr);
retVal = ret.c_str();
}
return retVal;
}
}
#endif
I know that all this #ifndef crap is not needed, since I only use this in one place and one place only so no cycle dependencies could occur, but I've added it anyway [it doesn't change when I remove it].
So.. path to the JniHelper.h file is correct. It looks like this btw.:
JniHelper.h
#ifndef __ANDROID_JNI_HELPER_H__
#define __ANDROID_JNI_HELPER_H__
#include <jni.h>
#include <string>
#include "CCPlatformMacros.h"
namespace cocos2d {
typedef struct JniMethodInfo_
{
JNIEnv * env;
jclass classID;
jmethodID methodID;
} JniMethodInfo;
class CC_DLL JniHelper
{
public:
static JavaVM* getJavaVM();
static void setJavaVM(JavaVM *javaVM);
static jclass getClassID(const char *className, JNIEnv *env=0);
static bool getStaticMethodInfo(JniMethodInfo &methodinfo, const char *className, const char *methodName, const char *paramCode);
static bool getMethodInfo(JniMethodInfo &methodinfo, const char *className, const char *methodName, const char *paramCode);
static std::string jstring2string(jstring str);
private:
static JavaVM *m_psJavaVM;
};
}
#endif // __ANDROID_JNI_HELPER_H__
Okay.. now.. I use a makefile to build it [it's a part of a larger build process, but for this particular file it looks like this (it is located in the same directory as the .h and .cpp files I pasted here].
Android.mk
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := game_logic
LOCAL_SRC_FILES := \
AppDelegate.cpp \
DeviceInfoAndroid.cpp \
DeviceInfo.cpp \
../libs/lua/cocos2dx_support/LuaEngineImpl.cpp \
../libs/lua/cocos2dx_support/Cocos2dxLuaLoader.cpp \
../libs/lua/cocos2dx_support/LuaCocos2d.cpp \
../libs/lua/cocos2dx_support/LuaEngine.cpp \
../libs/lua/CocosDenshion_support/LuaSimpleAudioEngine.cpp \
../libs/lua/exts/luallthread/llthreads.c \
../libs/lua/exts/luasocket/auxiliar.c \
../libs/lua/exts/luasocket/buffer.c \
../libs/lua/exts/luasocket/except.c \
../libs/lua/exts/luasocket/inet.c \
../libs/lua/exts/luasocket/io.c \
../libs/lua/exts/luasocket/luasocket.c \
../libs/lua/exts/luasocket/mime.c \
../libs/lua/exts/luasocket/options.c \
../libs/lua/exts/luasocket/select.c \
../libs/lua/exts/luasocket/tcp.c \
../libs/lua/exts/luasocket/timeout.c \
../libs/lua/exts/luasocket/udp.c \
../libs/lua/exts/luasocket/unix.c \
../libs/lua/exts/luasocket/usocket.c \
../libs/lua/exts/lualoadexts.c \
../libs/lua/exts/luasocketscripts.c
LOCAL_C_INCLUDES := $(LOCAL_PATH)/../libs/cocos2dx \
$(LOCAL_PATH)/../libs/cocos2dx/platform \
$(LOCAL_PATH)/../libs/cocos2dx/include \
$(LOCAL_PATH)/../libs/cocos2dx/lua_support \
$(LOCAL_PATH)/../libs/CocosDenshion/include \
$(LOCAL_PATH)/../libs/lua/lua \
$(LOCAL_PATH)/../libs/lua/tolua \
$(LOCAL_PATH)/../libs/lua/cocos2dx_support \
$(LOCAL_PATH)/../libs/lua/CocosDenshion_support \
$(LOCAL_PATH)/../libs/lua/exts \
$(LOCAL_PATH)/../libs/lua/exts/luallthread \
$(LOCAL_PATH)/../libs/lua/exts/luasocket \
$(LOCAL_PATH)/../libs/cocos2x/platform/android/jni \
LOCAL_LDLIBS := -L$(call host-path, $(LOCAL_PATH)/../Android/libs/$(TARGET_ARCH_ABI)) \
-L$(call host-path, $(LOCAL_PATH)/../libs/cocos2dx/platform/third_party/android/libraries/$(TARGET_ARCH_ABI)) -lcurl \
-lcocos2d \
-lcocosdenshion \
-llua
include $(BUILD_SHARED_LIBRARY)
As you can see I've added the path to the JniHelper.h file to the LOCAL_C_INCLUDES. I've tried removing the path and just using "JniHelper.h" but it throws an error saying that file does not exist.
The error I get during build is:
Compile++ thumb : game_logic <= DeviceInfoAndroid.cpp
jni/../../Classes/DeviceInfoAndroid.cpp: In function 'const char* getAndroidDeviceId()':
jni/../../Classes/DeviceInfoAndroid.cpp:10: error: 'JniMethodInfo' was not declared in this scope
jni/../../Classes/DeviceInfoAndroid.cpp:10: error: expected ';' before 't'
jni/../../Classes/DeviceInfoAndroid.cpp:12: error: 'JniHelper' has not been declared
jni/../../Classes/DeviceInfoAndroid.cpp:12: error: 't' was not declared in this scope
jni/../../Classes/DeviceInfoAndroid.cpp:17: error: expected primary-expression before ')' token
make: *** [obj/local/armeabi/objs-debug/game_logic/DeviceInfoAndroid.o] Error 1
Any tips? What have I done wrong? I know that in order to write in C++ I have a lot to learn, but as I mentioned... I'm not going to write in C++, it's just a few lines of code I need to create for every device type I have to support in my game. I'm already done with objective-c and c++ mixing to get iOS device id.
EDIT: when removing some comments of mine I've managed to remove include of DeviceInfoAndroid.cpp. I've corrected the code above. Sorry about that.
After your edit, here's my updated answer:
JniMethodInfo exists in the namespace cocos2d, so you should reference to it as:
cocos2d::JniMethodInfo t;
Same goes for JniHelper:
if (cocos2d::JniHelper::getStaticMethodInfo
etc.
Answer before your edits: (not relevant anymore, but saved here for reference)
You need to move the includes from the header file to the cpp file. DeviceInfoAndroid.h is not automatically included in DeviceInfoAndroid.cpp. You must include it manually.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With