Java 回调 lua function 问题

目前是这样的一个需求

打开相册,并传回选择的照片资源fullpath

我利用luaj调用java函数openSystemGalleryForSelect
并向java传递了一个lua处理函数,这个处理函数在Java代码中没有立即调用,而是retain了一下
等待处理结束后,在另外一个Java函数onImageSelected中回调。 遇到的问题是,Java函数中img变量的值是正确的,而调用lua function 时,打印的内容却是空值, 而不是">>>>imagePath"这种形式

-- xx 为我自己封装的库
xx.Helper:openSystemGalleryForSelect(function(imagePath)
    xx.ui.Hint.showMsg(">>>>imagePath is:"..imagePath)
end)

-- xx库中的该方法实现如下:
local openSystemGalleryForSelect
openSystemGalleryForSelect = function(self, callback) 
    local args = {callback}
    local sigs = "(I)V"
    local ok = luaj.callStaticMethod(className,"openSystemGalleryForSelect",args,sigs)
    if not ok then 
        -- 调用失败
    end 
end 

Java代码如下:

// 打开系统相册 选择图片后回调
    public static void openSystemGalleryForSelect(final int luaFunc) {
        if (_select_photo_lua_func != 0){
            Cocos2dxLuaJavaBridge.releaseLuaFunction(_select_photo_lua_func);
            _select_photo_lua_func = 0;
        }
        _select_photo_lua_func = luaFunc;
        Cocos2dxLuaJavaBridge.retainLuaFunction(_select_photo_lua_func);

        Intent intent = new Intent(Intent.ACTION_PICK, null);
        intent.setDataAndType(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, IMAGE_UNSPECIFIED);
        activity.startActivityForResult(intent, PHOTOSELECT);
    }
    
// 选择完照片的回调
public static void onImageSelected(final String img) {
        if (_select_photo_lua_func != 0){
            Cocos2dxGLSurfaceView.getInstance().queueEvent(new Runnable() {
                @Override
                public void run() {
                    Cocos2dxLuaJavaBridge.callLuaFunctionWithString(_select_photo_lua_func, img);
                    Cocos2dxLuaJavaBridge.releaseLuaFunction(_select_photo_lua_func);
                    _select_photo_lua_func = 0;
                }
            });
        }
    }

有人可以解惑?

看不出问题出在哪里
但是我一般都是lua这边写的global函数,java这边直接调用,你可以这样试试,如果这样可以的话,说明问题出在对lua函数的传递和保存上面。

谢谢回复, global的解决方案没有解决本质问题,这里最合适或者最直接的方式,应该是传递一个局部函数,由Java端持有并回调,这是比较符合编程思路和习惯。

就目前我并没有写全局的函数,因为工程这里我已经要求不允许写全局函数,以免对全局空间造成不必要的污染。

我这里都采用的是发送用户事件来解决这个问题。

openSystemGalleryForSelect 中:
local sigs = “(I)V”
改为
local sigs = {"(I)V"}

另 public static void openSystemGalleryForSelect(final int luaFunc) 中:
去掉: Cocos2dxLuaJavaBridge.retainLuaFunction(_select_photo_lua_func);

详见 http://dualface.github.io/blog/2013/01/01/call-java-from-lua/#E5B08620lua20function20E4BD9CE4B8BAE58F82E695B0E4BCA0E98092E7BB9920java20E696B9E6B395:
将一个 Lua function 以引用 ID 的形式传入 Java 时,luaj 会自动增加引用 ID 的计数器,所以在 Java 方法里可以放心的异步调用 Lua function。但在不需要使用该 Lua function 后,一定要调用 releaseLuaFunction() 减少该引用 ID 的计数器。当计数器为 0 时,会自动释放该 Lua function

源码中:
LuaJavaBridge.cpp
int LuaJavaBridge::callJavaStaticMethod(lua_State *L)
{

case TypeInteger:
if (lua_isfunction(L, index))
{
args[i].i = retainLuaFunction(L, index, NULL);
}
else
{
args[i].i = (int)lua_tonumber(L, index);
}
break;

}

这个是错误的,luaj.lua中是如下写法:

local luaj = {}

local callJavaStaticMethod = LuaJavaBridge.callStaticMethod

local function checkArguments(args, sig)
    if type(args) ~= "table" then args = {} end
    if sig then return args, sig end

    sig = {"("}
    for i, v in ipairs(args) do
        local t = type(v)
        if t == "number" then
            sig[#sig + 1] = "F"
        elseif t == "boolean" then
            sig[#sig + 1] = "Z"
        elseif t == "function" then
            sig[#sig + 1] = "I"
        else
            sig[#sig + 1] = "Ljava/lang/String;"
        end
    end
    sig[#sig + 1] = ")V"

    return args, table.concat(sig)
end

function luaj.callStaticMethod(className, methodName, args, sig)
    local args, sig = checkArguments(args, sig)
    --echoInfo("luaj.callStaticMethod(\"%s\",\n\t\"%s\",\n\targs,\n\t\"%s\"", className, methodName, sig)
    return callJavaStaticMethod(className, methodName, args, sig)
end

return luaj

显然传入的sig 要被解析成字符串返回。 至于后者, 去掉retainLuaFunction 这个你是对的。

请注意这行:
if sig then return args, sig end

请问这个问题最终您的解决方法是?