把这几天瞎搞的东西总结一下.
环境配置什么的也比较烦. ndk.java.在cocos2dx的环境中都有配置.参1
很基础很基础很基础的环境配置.
1.android与C 之间的调用
android通过JNI 来调用C(不带C++玩.extern "C"),
1.1android调用C
如果要在Eclipse中用C/C++编译要在工程上选android tools 的add native support,来编译c/c++.对于cocos2dx的理论上已经设置好了. 当然如果没有. 那还是用cocos compile来编吧. 自己做的darkc项目的工程如果加上后会有问题. 可能是配置的原因 .留个坑....
在src下com.example.wifiip包MainActivity.java文件中声明C方法: native public void onBtnClick();
可以选择用javah来把头c的头文件编译出来,里面会有固定格式的函数声明.
Run->Extern tools
嗯 , 具体 的参数 作用 不明. 留坑 ....后面还要用的javap用于签名java函数.用于jni层c call java.如果明白规则 也可不用.主要是为了明确descriptor 同上
1 /*DO NOT EDIT THIS FILE - it is machine generated*/
2 #include
3 /*Header for class com_example_wifiip_MainActivity*/
4
5 #ifndef _Included_com_example_wifiip_MainActivity6 #define _Included_com_example_wifiip_MainActivity
7 #ifdef __cplusplus8 extern "C"{9 #endif
10 /*
11 * Class: com_example_wifiip_MainActivity12 * Method: onBtnClick13 * Signature: ()V14 */
15 JNIEXPORT voidJNICALL Java_com_example_wifiip_MainActivity_onBtnClick16 (JNIEnv *, jobject);17
18 #ifdef __cplusplus19 }20 #endif
21 #endif
函数明是有规则的. 对照上面那个java文件,如果知道规则也可以不用生成.直接在写个定义
在cpp文件中完成实现代码.
android.mk文件中入相关的编译文件和头文件以及相应的指令. 参2
然后编译跑就行了. 在java代码中要调用
static{
System.loadLibrary("wifiIP");
}
总是忘记....
其实不太难
1.2 c call java
只要在jni层的c/c++代码中加入相应的代码就可以了
调用静态函数
//获取 MainActivity类,不是对象,对象已经有了是:objActivity
jclass clsActivity = pJniEnv->FindClass("com/example/wifiip/MainActivity");///获取类中的函数 getWifiAddress的函数ID,第三个参数填写该函数的函数签名
jmethodID method = pJniEnv->GetMethodID(clsActivity, "getWifiAddress", "()I");///调用java层函数
jobject object = pJniEnv->NewLocalRef(pJobject);int nIp = pJniEnv->CallIntMethod(object, method);
非静态函数
longstatus;
jclass cls;
jmethodID mid;
jint square;
jboolean not;
jobject jobj;
cls= (*env)->FindClass(env, "com/example/hellojni/HelloJni");if(cls !=0)
{
jmethodID construction_id= (*env)->GetMethodID(env, cls, "", "()V");if (construction_id ==0) {
__android_log_print(ANDROID_LOG_INFO,"pvvvvvv_printStringJNi", "Result of construction_id== 0");
}
jobject mTestProvider= (*env)->NewObject(env, cls, construction_id); mid = (*env)->GetMethodID(env, cls, "doLogin", "(ZZ)I");if(mid !=0)
{
square= (*env)->CallIntMethod(env, mTestProvider, mid, JNI_TRUE, JNI_TRUE);
__android_log_print(ANDROID_LOG_INFO,"pvvvvvv_printStringJNi","doLogin %d",square);
}
}
这里有一个问题在于调用的android中的界面线程时要小心. 在调用的相关函数中Context context, 这个参数不能再传this. 这地方坑我好久.因为实际上这里你是从外面调入. 不在一个线程中.就是空, 完全 不知道 你是谁啊.this毛线. 写个静态的存起this来或是传入都可以.
实验例子是:HelloJni.
2.lua与C 之间的调用
参3. 写的十分详细. 我就简单写下吧. 参4
c 与 lua 是利用栈 来交互的. 纯C环境下的也实现. 都是基于cocos下的. 不用自己搞 环境 - -!
在cocos环境 lua调用C 需要把c函数注册进lua中.
auto engine =LuaEngine::getInstance();
ScriptEngineManager::getInstance()->setScriptEngine(engine);
LuaStack* stack = engine->getLuaStack();
stack->setXXTEAKeyAndSign("2dxLua", strlen("2dxLua"), "XXTEA", strlen("XXTEA"));
lua_State*L = stack->getLuaState();
lua_register(L,"test_lua_bind", test_lua_bind);
也可以通过ScriptEngineManager类从头取得当前的LuaEngine对象,然后再getLuaStack()方法 得到封装的LuaStack对象,再调用getLuaState()得到原始的lua_State结构指针。只要知道了入 口位置,其他一切就不成问题了,还是挺简单的。
感兴趣的话可以去看一下ScriptEngineManager类的详细定义,在frameworks/cocos2d- x/cocos/base/CCScriptSupport.h文件中。
这个是直接注册成一个全局函数 , 实际在dark工程中是注册进名字空间中. 具体见工程....
2.2 c++调用lua
lua_State* pL =lua_open();
luaopen_base(pL);/*执行脚本*/luaL_dofile(pL,"helloLua.lua");/*把helloAdd函数对象放到栈中*/lua_getglobal(pL,"helloAdd");/*把函数所需要的参数入栈*/lua_pushnumber(pL,10);
lua_pushnumber(pL,5);/*执行函数,第一个参数表示函数的参数个数,第二个参数表示函数返回值个数 ,
Lua会先去堆栈取出参数,然后再取出函数对象,开始执行函数*/lua_call(pL,2, 1);int iResult = lua_tonumber(pL, -1);
依然是利用栈的方式 .
在cocos 环境下简单的好多.
写一个全局的方法.
auto luaStack = cocos2d::LuaEngine::getInstance()->getLuaStack();
lua_State* L = luaStack->getLuaState();
lua_getglobal(L,"onSdkInitCallBack"); /*query function by name, stack: function*/
if (!lua_isfunction(L, -1))
{
CCLOG("[LUA ERROR] name '%s' does not represent a Lua function", "onSdkInitCallBack");
lua_pop(L,1);return;
}
luaStack->executeFunction(0);
3.android与lua之间的调用.
本来理解 lua 需要先调
static public void showAlertDialog(finalString title,final String message, final intluaCallbackFunction) {
s_instance.runOnUiThread(newRunnable() {
@Overridepublic voidrun() {
doSdkLogin(false, true);
AlertDialog alertDialog= newAlertDialog.Builder(s_instance).create();
alertDialog.setTitle(title);
alertDialog.setMessage(message);
alertDialog.setButton("OK", newDialogInterface.OnClickListener() {
@Overridepublic void onClick(DialogInterface dialog, intwhich) {
s_instance.runOnGLThread(newRunnable() {
@Overridepublic voidrun() {
Cocos2dxLuaJavaBridge.callLuaFunctionWithString(luaCallbackFunction,"xxxCLICKEDvvvxxx");
Cocos2dxLuaJavaBridge.releaseLuaFunction(luaCallbackFunction);
}
});
}
});
alertDialog.setIcon(R.drawable.icon);
alertDialog.show();
}
});
}
用 c.再通过jni调用java 实际上这东西 已经在cocos下集成好了.luaj直接使用就可以了. 想想全是眼泪....
注意 GL线程. 和ui线程 之间的使用
4.cocos2d-x 3.0下绑定lua
绑定类进 参3里写的很详细....... 实在没啥可总结的. 实际项目只是注册函数进实现在. 一会818看有没有他们自己注册进去的类.
参考