[SOLVED] Sending messages from Java to Lua

Hi there all! I have a game. It is being built for iOS and Android. The app communicates to both iOS and Java via the EasyNDK/NDKHelper classes. When a message needs to be sent back to Lua, based on a message sent to the respective iOS/Android code, it will respond back by calling a C++ static class method. The C++ static class method gets an instance of the LuaStack with the following code:

void LuaCall::VideoAdsEnabled(bool isAvailable)
{
    lua_State *ls = LuaEngine::getInstance()->getLuaStack()->getLuaState();

    std::string filefullpath = CCFileUtils::getInstance()->fullPathForFilename("LuaCallbacks.lua");
    int isOpen = luaL_dofile(ls, filefullpath.c_str());
    if (isOpen != 0) {
        CCLOG("VideoAdsEnabled: Open Lua Error: %i", isOpen);
        return;
    }
    
    lua_getglobal(ls, "VideoAdsEnabled");
    lua_pushboolean(ls, isAvailable);
    lua_call(ls, 1, 0);
}

This looks pretty vanilla, right? Well, it works great in iOS. However, when calling from Java the if (isOpenn != 0) { always returns true. When I comment out the if statement, so that it calls the lua_* methods directly, the app crashes.

The only thing I can think of is that the instance of LuaState that is returned by LuaState::getInstance() is different for my code than the one created in Cocos2d. I have since debunked this idea as I added a CCLOG statement in the LuaState::getInstance() method to ensure that the same instance is being returned. The log statement only ever gets called once, so I believe it’s safe to assume that I’m accessing the same instance.

I’m fairly new to building C, C++ projects for Android. So any help would be appreciated.

I think a better question to ask is, “Is there a built-in way to pass messages to/from Lua and host applications?”. I’ve been using dispatchCustomEvent with some success. But now I need to actually send back data.

Thank you in advance!

OK… I believe I may know what’s going on.

I’m assuming that luaL_dofile() must open the file first before I can start using the lua_* commands. Initially I thought it was just checking to see if the file was open, but I think it may also be setting up the context in which variables can be pushed into the Lua state. I could be wrong… in any case, I printed out the filefullpath and received the path “assets/src/LuaCallbacks.lua”. When I look in my proj.android/assets/src/ directory I see that the file “LuaCallbacks.lua” exists. Now… I’ve had issues in the past where opening a file, using the path provided by fullPathForFilename, would fail to find the file; as it provides a relative path and not the absolute path to the file. I’m going to go out on a limb here and say this is failing because it’s not loading the file correctly.

I’ll see what I can do to find the absolute path to the file. If anyone knows, please let me know! Thank you.

I now have a better understanding. It looks like my assumption was correct. luaL_dofile() loads, compiles and runs the file and the pops the code off the stack. Kind of a one-shot execution. Also, it’s not possible to get the absolute path, so far as I know, as the Lua code is part of the apk; which is compiled.

After poking around a bit I found the luaL_dostring() function which does exactly what I want it to do. I feel that it’s actually a better approach as I’m not loading an entire file. Rather, I am simply executing a method within the Lua state. Here’s an example:

void LuaCall::VideoAdsEnabled(bool isAvailable)
{
    lua_State *ls = LuaEngine::getInstance()->getLuaStack()->getLuaState();

    int success = luaL_dostring(ls, "VideoAdsEnabled(true)");
    if (success != 0) {
        CCLOG("VideoAdsEnabled: Failed to call VideoAdsEnabled");
    }
}

The VideoAdsEnabled is already into the Lua state. So it’s simply a matter of calling the function.