Luabind调用约定问题
我正在使用 Luabind 时遇到问题,不确定如何解决,而不使用一些过于简单的解决方案。
Luabind似乎只允许使用__cdecl的调用约定绑定函数。在我的当前项目中,所有暴露给扩展/插件的功能都使用了__stdcall。这使得我无法直接绑定暴露的对象,而必须为暴露的对象创建包装器。这样做也无妨,但需要包装的对象很多。
例如,一个对象可以像这样:
结构IObject
{
void__stdcall SomeFunc1(void);
void__stdcall SomeFunc2(const char *);
};
结构IObjectContainer
{
IObject *__ stdcall GetObject(int);
IObject *__ stdcall GetObject(const char *);
};
结构IObjectCore
{
IObjectContainer *__ stdcall GetObjectContainer();
};
目前,我无法更改整个项目的调用约定,因此我正在寻找解决方案,以修补Luabind与__stdcall函数一起使用的能力。我对模板和boost不是很熟悉,因此我个人不确定从哪里开始尝试添加使用__stdcall函数的能力。
参考资料:
- Lua 5.1.4
- Luabind 0.9.1
- VS2010
Lua和Luabind都是最新版本的库。(由于项目限制原因,不使用Lua 5.2,但如果有针对5.2 / Luabind的__stdcall修复方法,我也很乐意采用。)
我只能找到一个非常古老的版本的Luabind的修复方法,但是在网上流传的补丁与当前Luabind代码完全不符。
如果还需要其他信息,请随时问。
当将OpenGL(使用GLEW函数)绑定到Lua时,我遇到了完全相同的问题,并使用可变模板解决了它。
现在,如果该函数是全局的,并且您在编译时知道其地址,则可以使用以下代码:
template<typename Signature>
struct wrap_known;
template<typename Ret, typename... Args>
struct wrap_known<Ret __stdcall (Args...)> {
template <Ret __stdcall functor(Args...)>
static Ret invoke(Args... arguments) {
return functor(arguments...);
}
};
// 我知道使用宏通常不是很好的主意,但是它只是更短
#define wrap(f) wrap_known<decltype(f)>::invoke<f>
然后,在绑定时使用宏如下所示:
luabind::def("Clear", wrap(glClear)),
luabind::def("Vertex4f", wrap(glVertex4f))
但是,在您的情况下,我们有一堆成员函数而不是上述的全局函数。
这是使用 __stdcall 调用约定包装成员函数的代码:
template<typename Signature>
struct wrap_mem;
template<typename Sub, typename Ret, typename... Args>
struct wrap_mem<Ret(__stdcall Sub::*) (Args...)> {
template <Ret(__stdcall Sub::*functor) (Args...)>
static Ret invoke(Sub* subject, Args... arguments) {
return (subject->*functor)(arguments...);
}
};
#define wrap_member(f) wrap_mem<decltype(f)>::invoke<f>
像这样使用它:
struct A {
int __stdcall my_method(double b) {
return 2;
}
};
// ...
luabind::class_<A>("A")
.def("my_method", wrap_member(&A::my_method))
但是,有时您不那么幸运,无法在编译时知道函数的地址,例如使用GLEW时。对于诸如 glUniform*f,glGetUniformLocation 等函数,"wrap" 宏将不起作用,因此我为封装在运行时已知的函数制作了另一个版本:
template<typename Signature>
struct wrap_unknown;
template<typename Ret, typename... Args>
struct wrap_unknown<Ret (__stdcall*) (Args...)> {
template <Ret (__stdcall** functor)(Args...)>
static Ret invoke(Args... arguments) {
return (**functor)(arguments...);
}
};
#define wrap_ptr(f) wrap_unknown<decltype(f)>::invoke<&f>
(如果上述代码让您感到难以理解,这实际上是一个好兆头)
现在,您可以像这样绑定GLEW函数:
luabind::def("Uniform4f", wrap_ptr(glUniform4f)),
luabind::def("GetUniformLocation", wrap_ptr(glGetUniformLocation))
只是不要让我再写另一个版本,用于绑定运行时已知的成员指针 :)
如果由于某种原因您不想使用C++11,请查看此处以了解如何在C++03中将函数参数和返回值传递为模板参数的方法。
- 如何将两个不同的lua文件合成一个 东西有点长 大佬请耐心看完 我是小白研究几天了都没搞定
- 如何在roblox studio中1:1导入真实世界的地形?
- 求解,lua_resume的第二次调用继续执行协程问题。
- 【上海普陀区】内向猫网络招募【Skynet游戏框架Lua后端程序员】
- SF爱好求教:如何用lua实现游戏内调用数据库函数实现账号密码注册?
- Lua实现网站后台开发
- LUA错误显式返回,社区常见的规约是怎么样的
- lua5.3下载库失败
- 请问如何实现文本框内容和某个网页搜索框内容连接,并把网页输出来的结果反馈到另外一个文本框上
- lua lanes多线程使用
- 一个kv数据库
- openresty 有没有比较轻量的 docker 镜像
- 想问一下,有大佬用过luacurl吗
- 在Lua执行过程中使用Load函数出现问题
- 为什么 neovim 里没有显示一些特殊字符?
- Lua比较两个表的值(不考虑键的顺序)
- 有个lua简单的项目,外包,有意者加微信 liuheng600456详谈,最好在成都
- 如何在 Visual Studio 2022 中运行 Lua 代码?
- addEventListener 返回 nil Lua
- Lua中获取用户配置主目录的跨平台方法
非常遗憾,由于长时间没有活动并且搜索没有得到更多的答案,我与项目开发人员交谈,将整个项目取消了 __stdcall。因此,绑定现在都可以通过 __cdecl 正常工作。这不是我想要采取的方法,但现在计划中的事情都正常工作了。