关于jsb绑定的两点问题

我们游戏中,在之前是使用反射进行ts(js)<—>c++通信互调的,但是这样做的话,一开始还好,后来多了如官方文档所言,大量的反射有如灾难一样。于是,需要用到jsb绑定,参考了官方文档后,决定先尝试手动绑定,弄清原理:

Cocos Creator 版本:2.3.3

jsb_test_manual.cpp(参考了jsb_cocos2dx_audioengine_auto.cpp)

bool JSB_testBindCallback(se::State& s)
{
    const auto& args = s.args();
    size_t argc = args.size();
    CC_UNUSED bool ok = true;

    do {
        if (argc < 0 || argc > 2)
        {
            break;
        }

        std::string json;
        ok &= seval_to_std_string(args[0], &json);
        SE_PRECONDITION2(ok, false, "JSB_testBindCallback arguments index: 0");

        if (argc == 1)
        {
            GameNS::myCPPFunction(json, nullptr);
            return true;
        }

        if (argc == 2)
        {
            GameNS::Callback func;
            if (args[1].isObject() && args[1].toObject()->isFunction())
            {
                se::Value jsThis(s.thisObject());
                se::Value jsFunc(args[1]);
                
                jsFunc.toObject()->root();
                auto lambda = [=](const std::string & ret) -> void
                {
                    se::ScriptEngine::getInstance()->clearException();
                    se::AutoHandleScope hs;

                    CC_UNUSED bool ok = true;
                    se::ValueArray cb_args;
                    cb_args.resize(1);
                    ok &= std_string_to_seval(ret, &cb_args[0]);
                    if (ok)
                    {
                        se::Value rval;
                        se::Object *thisObj = jsThis.isObject() ? jsThis.toObject() : nullptr;
                        se::Object *funcObj = jsFunc.toObject();
                        bool succeed = funcObj->call(cb_args, thisObj, &rval);
                        if (!succeed)
                        {
                            se::ScriptEngine::getInstance()->clearException();
                        }
                        return;
                    }
                };
                func = lambda;
            }
            GameNS::myCPPFunction(json, func);
            return true;
        }

    }while (false);

    SE_REPORT_ERROR("JSB_testBindCallback: Invalid number of arguments");
    return false;
}
SE_BIND_FUNC(JSB_testBindCallback)

test.h

namespace GameNS {
    using Callback = std::function<void(const std::string&)>;
    void myCPPFunction(std::string json, const Callback & callback);
}

test.cpp

Callback testCallback = nullptr;
void myCPPFunction(std::string json, const Callback & callback)
{
    testCallback = callback;
    auto obj = getInstanceObj();
    JniHelper::callObjectVoidMethod(obj, "game/Test", "myJavaFunction", json);
}

extern "C" {
    void Java_game_Test_onCallback(JNIEnv *env, jobject thiz, jstring string) {
        if (GameNS::testCallback) {
            GameNS::testCallback(JniHelper::jstring2string(string));
        }
        GameNS::testCallback = nullptr;
    }
}

test.java

package game;
public class Test {
    private Handler handler = new Handler(Looper.getMainLooper());

    public static Test getInstance() {
        if (instance == null) {
            synchronized (Test.class) {
                instance = new Test();
            }
        }

        return instance;
    }

    public native void onCallback(String string);
    public void myJavaFunction(String jsonStr) {
        JSONObject json = null;
        try {
            json = new JSONObject(jsonStr);
        } catch (JSONException e) {
            e.printStackTrace();
        }

        handler.postDelayed(new Runnable() {
                @Override
                public void run() {
                    Log.d("Test", "handler post delayed");
                    onCallback("{}");
                }
        }, 1000);
    }
}

ts调用

jsb.test.testBindCallback("{}", this.myTestMethod.bind(this));

目前有两个问题:
1)在JSB_testBindCallback中,如果se::AutoHandleScope hs;这一句,按我参考原有的绑定写法,是放到lambda中的,但是如果myJavaFunction中立即调用onCallback则完全没有问题,但是,如果handler延时模拟真实的异步回调,lambda在执行到se::AutoHandleScope hs;这一句时,就必然会报错,v8::Isolate::GetCurrent()NULL,但是如果放到lambda外面则正常,这是为什么?

2)在JSB_testBindCallback中,我执行了一次jsFunc.toObject()->root();,是否需要在调用一次jsFunc.toObject()->unroot();?目前这样写是否会导致内存泄漏(尽管我看了文档对于root/unroot的描述,还是一头雾水)

为什么不用自动绑定。难道自动绑定不好用么。

我个人觉得,不好用,哈哈哈,我都是手动自己写·····

所以我在哪里写错了。。。

自动绑定是 sm, v8都不支持 绑定个毛线 :innocent:

我想问问大佬是谁,见过?

大佬,我是行知

结论:官方太坑

:rofl::rofl::rofl::rofl:

现在回复贴是有了,倒成了聊天吐槽的了 :joy: :joy: :joy: :joy: