总结关于lua, c , android,在 cocos2d-x 之间的调用方法
把这几天瞎搞的东西总结一下.
环境配置什么的也比较烦. 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 <jni.h> 3 /* Header for class com_example_wifiip_MainActivity */ 4 5 #ifndef _Included_com_example_wifiip_MainActivity 6 #define _Included_com_example_wifiip_MainActivity 7 #ifdef __cplusplus 8 extern "C" { 9 #endif 10 /* 11 * Class: com_example_wifiip_MainActivity 12 * Method: onBtnClick 13 * Signature: ()V 14 */ 15 JNIEXPORT void JNICALL Java_com_example_wifiip_MainActivity_onBtnClick 16 (JNIEnv *, jobject); 17 18 #ifdef __cplusplus 19 } 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);
非静态函数
long status; 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, "<init>", "()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(final String title, final String message, final int luaCallbackFunction) { s_instance.runOnUiThread(new Runnable() { @Override public void run() { doSdkLogin(false, true); AlertDialog alertDialog = new AlertDialog.Builder(s_instance).create(); alertDialog.setTitle(title); alertDialog.setMessage(message); alertDialog.setButton("OK", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { s_instance.runOnGLThread(new Runnable() { @Override public void run() { 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看有没有他们自己注册进去的类.
参考
1. http://jingyan.baidu.com/article/3ea51489e7a9bd52e61bbac7.html
2. http://blog.csdn.net/yili_xie/article/details/4906865
3. http://cn.cocos2d-x.org/tutorial/show?id=1295
4. http://blog.csdn.net/musicvs/article/details/8440707
5. http://blog.csdn.net/xdw1985829/article/details/6900155
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。