我遇到Luabind的问题,我不确定如何在没有一些过度简化的解决方案的情况下解决问题。
Luabind似乎只允许使用__cdecl
调用约定绑定到函数。在我当前的项目中,使用__stdcall
公开了所有暴露给扩展/插件的功能。这使我无法直接绑定暴露的对象,而是必须为暴露的对象制作包装器。这很好,但是有很多对象需要包装。
例如,对象可能如下所示:
struct IObject
{
void __stdcall SomeFunc1( void );
void __stdcall SomeFunc2( const char* );
};
struct IObjectContainer
{
IObject* __stdcall GetObject( int );
IObject* __stdcall GetObject( const char* );
};
struct IObjectCore
{
IObjectContainer* __stdcall GetObjectContainer();
};
我没有选择更改当前调用约定的整个项目,所以我看到是否有人有解决方案可能修补Luabind使用__stdcall
函数。我不是最好的模板和增强功能,所以我个人不确定在哪里开始尝试添加使用__stdcall
功能的能力。
供参考,我正在使用:
Lua和Luabind都是他们版本的最新版本。 (出于项目限制的原因,不使用Lua 5.2,但如果对5.2 / Luabind有__stdcall
修复,我也很乐意接受它。)
我只能找到一个非常旧版本的Luabind来修复这个问题,但是仍然在网上浮动的补丁根本不符合当前的Luabind代码。
如果需要任何其他信息,请随时提出。
答案 0 :(得分:2)
可悲的是,由于不活跃而没有更多搜索的进一步答案,我与项目开发人员进行了交谈,并且整个项目都被剥夺了__stdcall。所以现在绑定都可以通过__cdecl正常工作。不是我想采取的路线,但事情正在按计划进行。
答案 1 :(得分:1)
在将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...);
}
};
// I know using macro is generally a bad idea but it's just shorter
#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,here you can find out how to pass function arguments and return value as template parameters in C++03。