C++ - 在Lua C模块中调用Lua函数而不使用自定义的.lib文件

3
我有一个应用程序,它使用修改版的Lua 5.2。Lua嵌入在exe中,就我所知(使用Dependency Walker),没有导出其Lua函数的符号。我没有这个应用程序的源代码。我需要为Lua编写C模块,以便与这个应用程序一起使用。
我成功地在这个应用程序处理的Lua文件中进行了require,但是只要我尝试调用任何lua_*函数,应用程序就会崩溃并显示“访问冲突”错误。
有没有办法找到嵌入式Lua函数的地址/名称并调用它们?
我问过应用程序开发人员是否允许我这样做,他们似乎不在意。唯一的问题是禁止修改应用程序本身。
更新:就我所见,我之所以遇到“访问冲突”,是因为我正在尝试使用Lua代理库,并且它无法将调用传递给exe Lua C函数。如果我不使用Proxy DLL,我会收到“检测到多个VMs”的消息。有没有办法解决这个问题?
我的Lua C模块代码:
#if defined(WIN32) || defined(_WIN32)
#  define LUA_BUILD_AS_DLL   /* for #define LUA_API __declspec(dllimport) */
#endif

#ifdef __cplusplus
extern "C" {
#endif

#include <lua.h>
#include <lauxlib.h>

#ifdef __cplusplus
}
#endif

#if defined(WIN32) || defined(_WIN32)
#  ifdef __cplusplus
#    define MY_LUA_API   extern "C" __declspec(dllexport)
#  else
#    define MY_LUA_API   __declspec(dllexport)
#  endif
#else
#  define MY_LUA_API     extern "C"
#endif

using namespace std;

static int Lmytest_test(lua_State *L) {
    // Check the arguments.
    int argn = lua_gettop(L);
    if (argn != 1 || !lua_isstring(L, 1)) {
        lua_pushstring(L, "Give me one string argument please!");
        lua_error(L);
    }
    lua_pushstring(L, "Hello world!");
    return 2;
}

static const struct luaL_Reg lib[] = {
    { "test", Lmytest_test },
    { NULL, NULL }
};

MY_LUA_API int luaopen_mytest(lua_State* L) {

    printf("Before newlib\n");

#if LUA_VERSION_NUM >= 502
    luaL_newlib(L, lib);
#else
    lua_createtable(L, 0, sizeof(lib) / sizeof(lib[0]));
    luaL_register(L, NULL, lib);
#endif

    printf("After newlib\n");

    return 1;
}

对于那些问“什么是Lua代理库”的人:

http://lua-users.org/wiki/LuaProxyDll

http://lua-users.org/wiki/LuaProxyDllTwo

http://lua-users.org/wiki/LuaProxyDllThree

http://lua-users.org/wiki/LuaProxyDllFour


你可以编写一个简单的C模块:int luaopen_hello(lua_State *L) { printf("Hello from C!\n"); return 0; }然后使用 require("hello") 加载它。如果它打印出了 Hello from C!,那么你可能在你的模块中做错了些什么;如果还打印出了“Access violation”,那么程序的作者已禁用了加载模块的功能。 - Henri Menke
使用您的示例,我没有收到“访问冲突”的错误。但是,如果我尝试调用任何lua_*函数,它将崩溃并显示此消息。 - user64675
1
请您能否展示一下您的库的工作示例?还有“Lua代理库”是什么鬼? - Kamiccolo
添加了代码和链接到Lua代理。 - user64675
2个回答

0

你完全可以编写一个C dll,如果Lua环境是一个兼容的Lua系统,那么你应该能够实现你想要做的事情。不过,有一些事情你需要检查:

  1. 确定你使用的系统中运行的Lua版本。这将让你确定你需要编译的库的类型。
print( _VERSION )
  1. 检查此Lua环境正在使用的其他dll模块。使用Dependency Walker或类似工具。它们应该使用luaopen_()类型的入口点。如果是这种情况,那么上面的入口点应该没问题。

  2. 检查您传递给方法的内容。您不能在Lua和dll之间传递lightdata(指针)-主要是因为它们的分配将位于不同的空间。您会从中获得访问冲突。

  3. 检查Lua系统可能使用的任何外部库。通常会发现类似lua5.1.dll等。您需要连接到此文件以确保您使用的方法将在同一个应用程序进程空间中。

通常,此类问题更可能是由于修改了Lua实现方式导致Lua字节码和接口不一致,因此很难构建。希望这可以帮助解决问题。

顺便说一句,使用Dependency Walker查看可用方法的exe和dll。Lua使用stdcall名称修饰,因此它们始终可见。 http://www.dependencywalker.com/


0
我需要为Lua编写C模块以与此应用程序一起使用。
嗯...你不能这样做。
如果他们的程序没有导出Lua的DLL接口,并且它没有加载Lua的DLL,那么这意味着它静态链接了Lua。除非你真的破解可执行文件,否则你的DLL模块将与主可执行文件不使用的Lua实现进行通信。这就是为什么你会遇到运行时崩溃的原因;两个不同的代码片段对同一内存进行通信是行不通的。
通过静态链接到Lua,应用程序的开发人员使用户基本上无法为其使用Lua编写自己的C模块,而不进行二进制文件的破解。
有没有办法找到嵌入式Lua函数的地址/名称并调用它们?
没有反编译器或非常好的汇编技能是不可能的。由于链接时间优化的存在,即使是这些方法也可能失败,因为某些Lua API可能已经被内联了。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接