将 Alien 包含在便携式应用程序中,C++
好吧,我已经搜索了很多,但似乎无法找到如何实现这一目标的答案或示例。
基本上,我有一个设计为可移植的应用程序(在 VS2010 中使用 VC++ 构建,但没有 MFC 或托管组件,原始 WinAPI)。我内置了 Lua 5.2,并允许用户在应用程序内编写脚本。我有多个粘合函数,这些函数暴露给处理各种 WinAPI 调用的 Lua 脚本。
但是,我希望能够做的是允许用户编写一个如下所示的脚本:
require[[Alien/alien]]
local mb = alien.User32.MessageBoxA
mb:types{ 'long', 'long', 'string', 'string', 'long' }
print(mb(0, "Hello World!", "Test", 64))
我似乎找不到一种方法来做到这一点。我不想要求用户安装Lua for Windows,并且最好不要有来自外星人的core.dll和struct.dll;当我尝试对 ./alien/ 中的这些 DLL 执行某些操作时,它在 Lua5.1.dll 中崩溃,因为我安装了 LuaForWindows,我卸载了 LFW,然后它只是指出 Lua5.1.dll 丢失。我的应用程序中内置了 Lua 5.2,因此显然 Alien rock 中的 core/struct DLL 期望 Lua5.1.dll 位于路径中。
我做了一次毫无价值的尝试,尝试将 Alien src 包含到项目中,但似乎也不起作用。
任何想法将不胜感激。我希望将其全部包含在我的应用程序中,但我会选择一个解决方案,其中包括将库包含在我的项目中以在发行版中构建和捆绑(如果这是唯一的选择)。
谢谢!
更新:
好的,谢谢 Ben Voigt!我想我快到了。我已经引入了 core.c 和 struct.c 并确保 libffi 的所有路径都在那里。一切编译都没有问题,直到我尝试在 core.c (alien.core src 文件)中调用 luaopen_alien_core,声称标识符未声明。我试图在试图进行调用的单独源文件中声明函数签名,编译会进一步进行,但无法抱怨未解析的外部。
显然,这现在可能是一个普遍的 C++ 问题(因为我只是这个领域的新手)。这是我的总体思路:
//core.c (from Alien project)
(...)
int luaopen_alien_core(lua_State *L) {
alien_register_library_meta(L);
alien_register_callback_meta(L);
alien_register_function_meta(L);
alien_register_buffer_meta(L);
lua_getglobal(L, "alien");
if(lua_isnil(L, -1)) {
lua_newtable(L);
lua_pushvalue(L, -1);
lua_setglobal(L, "alien");
}
lua_newtable(L);
lua_pushvalue(L, -1);
lua_setfield(L, -3, "core");
alien_register_main(L);
return 1;
}
//mysource.c (the file attempting to call luaopen_alien_core(L))
void initLua()
{
L = luaL_newstate();
luaL_openlibs(L);
luaopen_alien_core(L);
(...)
}
这无法开始编译,发出错误:
error C3861: 'luaopen_alien_core': identifier not found
这是有道理的,所以我将以下行添加到 myheader.h:
int luaopen_alien_core(lua_State *L);
这可以编译,但无法链接:
error LNK2001: unresolved external symbol "int __cdecl luaopen_alien_core(struct lua_State *)" (?luaopen_alien_core@@YAHPEAUlua_State@@@Z)
我已经尝试了几件事以我有限的经验可以想到,但没有什么可以满足这个错误。我什至尝试将 core.c 的内容移至 mysource.c 中,但这会造成完全不同的混乱,而且似乎是错误的做法。
我希望并想象,这真的很愚蠢,但我只是不确定如何让它调用 luaopen_alien_core,这似乎是我需要的最后一块。
再次感谢! }
Ok, I've searched quite a bit, but seem unable to find an answer or example for how to achieve this.
Basically, I have an app that is designed to be portable (built using VC++ in VS2010, but no MFC or managed components, raw WinAPI). I have Lua 5.2 built into it and allow the user to write scripts inside the application. I have multiple glued functions which are exposed to the Lua scripts which handle various WinAPI calls.
However, what I'd like to be able to do is allow the user to write a script in which looks something like this:
require[[Alien/alien]]
local mb = alien.User32.MessageBoxA
mb:types{ 'long', 'long', 'string', 'string', 'long' }
print(mb(0, "Hello World!", "Test", 64))
I simply cannot seem to find a way to do this. I do not want to require the user to install Lua for Windows and, ideally, there be no core.dll and struct.dll from alien; when I tried to do something with those DLLs in ./alien/, it was crashing in Lua5.1.dll because I had LuaForWindows installed, I uninstalled LFW, and then it just states that Lua5.1.dll is missing. I have Lua 5.2 built into my app, so obviously the core/struct DLLs from the Alien rock are expecting Lua5.1.dll to be in the path.
I made a worthless attempt to try to including the Alien src into the project, but doesn't seem to work that way either.
Any ideas would be greatly appreciated. I'd prefer it all be contained in my app, but I'll settle for a solution which involves including the libraries in my project to build and bundle in the distribution if that's the only alternative.
Thanks!
UPDATE:
Ok, thank you Ben Voigt! I think I'm almost there. I've pulled in core.c and struct.c and made sure all the paths are there for libffi. Everything compiles without issue, until I try to call luaopen_alien_core in core.c (the alien.core src file), claiming the identifier is undeclared. I've tried to declare the function signature in my separate source file that's trying to make the call, the compile gets further, but fails complaining of an unresolved external.
Clearly this is likely now a general C++ issue (as I'm only a novice in this area). Here's the general idea of what I have:
//core.c (from Alien project)
(...)
int luaopen_alien_core(lua_State *L) {
alien_register_library_meta(L);
alien_register_callback_meta(L);
alien_register_function_meta(L);
alien_register_buffer_meta(L);
lua_getglobal(L, "alien");
if(lua_isnil(L, -1)) {
lua_newtable(L);
lua_pushvalue(L, -1);
lua_setglobal(L, "alien");
}
lua_newtable(L);
lua_pushvalue(L, -1);
lua_setfield(L, -3, "core");
alien_register_main(L);
return 1;
}
//mysource.c (the file attempting to call luaopen_alien_core(L))
void initLua()
{
L = luaL_newstate();
luaL_openlibs(L);
luaopen_alien_core(L);
(...)
}
This fails to start compiling, issuing the error:
error C3861: 'luaopen_alien_core': identifier not found
Which makes sense, so I add the following line to myheader.h:
int luaopen_alien_core(lua_State *L);
This compiles, but fails to link with:
error LNK2001: unresolved external symbol "int __cdecl luaopen_alien_core(struct lua_State *)" (?luaopen_alien_core@@YAHPEAUlua_State@@@Z)
I've tried several things I can think of, with my limited experience, but nothing will satisfy this error. I even tried to move the contents of core.c into mysource.c, but that creates a whole different mess and seemed to be the wrong way to go as it is.
I'm hoping, and imagining, this is something really stupid, but I'm just not sure how to get it to call luaopen_alien_core, which seems to be the final piece I need.
Thanks again!
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我想象
require
指令会加载动态库并将其内容添加到活动的 Lua 引擎中。通过将 Alien 直接链接到您的代码中,您就不再需要动态库了。但是内容枚举代码不会运行,并且您不能使用
require
来运行它,否则它会寻找 DLL 文件(以及所有 DLL 依赖项)。因此,您应该找出
require
指令在加载 DLL 后调用了哪些函数,并在创建 Lua 引擎时调用这些函数。那么脚本既不需要也不允许以require [[Alien/alien]]
开头,但 Alien 对象将可用。I imagine that the
require
directive both loads a dynamic library and adds its contents to the active Lua engine.By linking alien directly into your code, you obviate the need for the dynamic library. But the content enumeration code won't have run, and you can't use
require
to run it, or else it'll go looking for a DLL file (along with all the DLL dependencies).So, you should find out what functions that
require
directive calls after loading the DLL, and call those when creating a Lua engine. Then it will neither be necessary nor allowed for the script to start withrequire [[Alien/alien]]
, but Alien objects will be available.