zoukankan      html  css  js  c++  java
  • 总结关于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

  • 相关阅读:
    识别IE11浏览器
    国庆过后老革命
    有些东西再忙也要做
    云计算
    SVN下Update出现代码文件删除状态问题
    如何避免历史回退到登录页面
    CodeSmith连Oracle
    NHibernate直接执行SQL进行插入
    nhibernate实体类主键ID赋值问题
    NHibernate不支持复杂的linq,就一定要用DataTable这么低级吗
  • 原文地址:https://www.cnblogs.com/blackcatx/p/3982228.html
Copyright © 2011-2022 走看看