我正在将Lua脚本添加到我们的应用程序中,我需要为GUI工具包实现绑定.我们使用的工具包是wxWidgets.
我正在使用Lua 5.1和luabind 0.9.1,到目前为止它运行良好.但是,我不确定如何最好地处理事件.例如,如果要在单击时创建按钮并打印字符串,则可以在C++中编写类似的内容
class MyClass : public wxFrame
{
MyClass (...)
{
b = new wxButton (this, -1, "Click me");
b->Bind (wxEVT_COMMAND_BUTTON_CLICKED, &MyClass::HandleButtonClick, this);
}
void HandleButtonClick (wxCommandEvent& ev)
{
wxMessageBox ("You clicked me");
}
}
Run Code Online (Sandbox Code Playgroud)
我在Lua做同样事情的梦想API看起来像这样:
b = wx.Button (frm, -1, "Click me")
b.on_click = function (ev)
print ("Button clicked")
end
Run Code Online (Sandbox Code Playgroud)
或者,允许多个事件处理程序:
b.on_click:add (function (ev)
print ("Button clicked again ...")
end)
Run Code Online (Sandbox Code Playgroud)
如果不可能,这样的东西更类似于C++ API:
b.bind (wx.EVT_COMMAND_BUTTON_CLICKED, function (ev)
print ("Yet again")
end)
Run Code Online (Sandbox Code Playgroud)
但是,我不知道如何使用Luabind实现这一点,而不为我想要使用的wxWidgets-library中的每个类编写包装类.
有什么建议?
或许Luabind可以通过某种方式自动创建辅助类(比如说"wxLuaEventPropagator")吗?因此,wxButton类为每个事件都有一个嵌套的wxLuaEventPropagator类("on_click",依此类推).再一次,我不想为我使用的wxWidgets中的每个类创建包装类,因为有一吨.
(是的,我知道wxLua)
(旁注:这是游戏编程)
使用LuaBind将整个类绑定到Lua很容易:
class test
{
test()
{
std::cout<<"constructed!"<<std::endl;
}
void print()
{
std::cout<<"works!"<<std::endl;
}
}
Run Code Online (Sandbox Code Playgroud)
//别的地方
module[some_lua_state]
[
class_<test>("test")
.def(constructor<>())
.def("print",&test::print)
];
Run Code Online (Sandbox Code Playgroud)
现在我可以在Lua中创建该类的实例并使用它:
lua_example.lua
foo = test() //will print "constructed!" on the console
foo:print() //will print "works!" on the console
Run Code Online (Sandbox Code Playgroud)
但是,现在我想将一个特定的测试实例绑定到Lua.这将使我能够将对象传递给Lua,例如Player类的实例,并执行以下操作:
Player:SetPosition(200,300)
Run Code Online (Sandbox Code Playgroud)
而不是采取艰难的方式,并有类似的东西
SetPosition("Player",200,300)
Run Code Online (Sandbox Code Playgroud)
相应的C++ SetPosition函数需要查找std :: map才能找到播放器.
这是否可能,如果是这样,我怎么能在LuaBind中做到这一点?
我有一个依赖std::shared_ptr很多的API(一个特定的GUI库),即它们通常用作函数参数并存储在其他对象中.例如,容器小部件(例如拆分器和框)将其子小部件存储在shared_ptrs中.现在我想通过luabind将此API映射到Lua.在理想的世界中,Luabind将在shared_ptrs中创建新对象,并允许我将这些对象直接传递给采用shared_ptr参数的函数.这似乎适用于单个类,例如:
luabind::class_<Button, std::shared_ptr<Button>>("Button")
Run Code Online (Sandbox Code Playgroud)
虽然我这样声明,但我可以公开和使用像void foo(std::shared_ptr<Button> const&).
现在,luabind手册提到为了使用类的层次结构,我必须对层次结构中的所有类使用相同的shared_ptr模板实例,例如
luabind::class_<BaseWidget, std::shared_ptr<BaseWidget>>("BaseWidget"),
luabind::class_<Button, BaseWidget, std::shared_ptr<BaseWidget>>("Button")
Run Code Online (Sandbox Code Playgroud)
现在我再也无法打电话了foo- 它将无法从Lua找到该功能.我可以以某种方式让luabind继续支持shared_ptrs中的传递按钮吗?此外,我想知道为什么luabind要求您对层次结构中的所有类使用相同的智能指针,而不是它们只能转换为基类指针.
我正在使用Luan Pavlik与Lua 5.1的主发行版的luabind 0.9.1,在Win XP SP3上的cygwin +最新补丁x86,增强1.48,gcc 4.3.4.Lua和boost是cygwin预编译的版本.
我已经在静态和共享版本中成功构建了luabind.
两个版本都通过了test_object_identity.cpp测试的所有测试EXCEPT,这两个版本都失败了.
我已经将问题追溯到以下问题:如果为NON内置类创建表中的条目(即,不是int,string等),则无法检索该值.
这是一段代码,演示了这一点:
#include "test.hpp"
#include <luabind/luabind.hpp>
#include <luabind/detail/debug.hpp>
using namespace luabind;
struct test_param
{
int obj;
};
void test_main(lua_State* L)
{
using namespace luabind;
module(L)
[
class_<test_param>("test_param")
.def_readwrite("obj", &test_param::obj)
];
test_param temp_object;
object tabc = newtable(L);
tabc[1] = 10;
tabc[temp_object] = 30;
TEST_CHECK( tabc[1] == 10 ); // passes
TEST_CHECK( tabc[temp_object] == 30 ); // FAILS!!!
}
Run Code Online (Sandbox Code Playgroud)
tabc [1]确实是10而tabc [temp_object]不是30!(实际上,似乎是零)
但是,如果我使用iterate来遍历tabc条目,则有两个条目具有CORRECT键/值对.
有任何想法吗?
BTW,像这样重载==运算符:
#include <luabind/operator.hpp>
struct test_param
{
int obj; …Run Code Online (Sandbox Code Playgroud) 我想使用与luabind超过10个参数的函数,但我得到一些C2784和C2780编译器错误(VS2012 Express).
似乎问题是使用的boost库的限制.在luabind中,可以设置LUABIND_MAX_ARITY选项,但这取决于boost的可能性.我怎么能克服这种限制?
谢谢!
码:
luabind::module(lua) [
luabind::class_<WkmParserDB>("WkmParserDB")
.def("insertInterface", &WkmParserDB::insertInterface)
.def("insertIntfStats", &WkmParserDB::insertIntfStats)
.def("intertIntfN1k", &WkmParserDB::intertIntfN1k)
];
Run Code Online (Sandbox Code Playgroud)
函数insertIntfStats有大约20个std :: string参数,没有别的.另外两个函数的参数少于8个(std :: string也是如此).当我评论".def("insertIntfStats",&WkmParserDB :: insertIntfStats)这一行时,它编译并运行.
错误:
Fehler 3 error C2784: "boost::mpl::vector12<R,const most_derived<T,Wrapped>::type&,A0,A1,A2,A3,A4,A5,A6,A7,A8,A9> luabind::detail::deduce_signature(R (__thiscall T::* )(A0,A1,A2,A3,A4,A5,A6,A7,A8,A9) const,Wrapped *)": template-Argument für "R (__thiscall T::* )(A0,A1,A2,A3,A4,A5,A6,A7,A8,A9) const" konnte nicht von "std::basic_string<_Elem,_Traits,_Alloc> " hergeleitet werden. d:\programmieren\luabind-0.9.1\luabind\class.hpp 311 1 wktools4
Fehler 4 error C2780: 'boost::mpl::vector12<R,const T&,A0,A1,A2,A3,A4,A5,A6,A7,A8,A9> luabind::detail::deduce_signature(R (__thiscall T::* )(A0,A1,A2,A3,A4,A5,A6,A7,A8,A9) const)': Erwartet 1 Argumente - 2 unterstützt d:\programmieren\luabind-0.9.1\luabind\class.hpp 311 1 wktools4
Fehler 5 error C2784: …Run Code Online (Sandbox Code Playgroud) 我目前正在开发一个基于插件的C++系统,它提供了一个Lua脚本界面,我选择使用luabind.我正在使用Lua 5和luabind 0.9,它们都是静态链接的,并且使用MSVC++ 8编译.我现在无法在luabind中绑定函数,因为它们是在派生类中定义的,而不是它的父类.
更具体地说,我有一个名为'IPlugin'的抽象基类,所有插件类都从该基类继承.当插件管理器初始化时,它会注册该类及其功能,如下所示:
luabind::open(L);
luabind::module(L) [
luabind::class_<IPlugin>("IPlugin")
.def("start", &IPlugin::start)
];Run Code Online (Sandbox Code Playgroud)
由于它只是在运行时知道哪些有效的插件类可用,我不得不以一种迂回的方式解决加载插件.插件管理器将工厂函数公开给Lua,它接受插件类的名称和所需的对象名称.工厂然后创建对象,将插件的类注册为继承自"IPlugin"基类,并立即调用创建的对象上的函数,该函数将自身注册为具有Lua状态的全局,如下所示:
void PluginExample::registerLuaObject(lua_State *L, string a_name)
{
luabind::globals(L)[a_name] = (PluginExample*)this;
}Run Code Online (Sandbox Code Playgroud)
我最初这样做是因为我在Lua确定对象的派生类最多时遇到了问题,就像我从插件管理器注册它一样,它只被称为'IPlugin'的子类型而不是特定的子类型.我不确定这是否甚至是必要的,但是它可以工作,随后可以从'a_name'下的Lua访问创建的对象.
但是,我遇到的问题是,无法使用派生类中定义的函数,这些函数在父类中根本没有声明.在基类中定义的虚函数(例如上面的'start')工作正常,并且在新对象上从Lua调用它们运行来自'PluginExample'类的相应重新定义的代码.但是如果我向'PluginExample'添加一个新函数,这里的例子是一个不带参数并返回void的函数,并像这样注册它:
luabind::module(L) [
luabind::class_<PluginExample, IPlugin>("PluginExample")
.def(luabind::constructor<PluginManager&>())
.def("func", &PluginExample::func)
];Run Code Online (Sandbox Code Playgroud)
在新对象上调用'func'会产生以下Lua运行时错误:
No matching overload found, candidates: void func(PluginExample&)
我正确使用':'语法,因此不需要'self'参数,似乎突然Lua无法再确定对象的派生类型.我确信我做错了,可能与我的系统架构所需的两步绑定有关,但我无法弄清楚在哪里.我非常感谢一些帮助=)
如何遍历luabind类(在lua或c ++中)?
class 'A'
function A:__init()
-- Does not work
-- self is userdata, not a table
for i, v in pairs(self) do
end
end
Run Code Online (Sandbox Code Playgroud)
谢谢
假设我有这样一个类:
class A
{
public:
A(){}
~A(){}
};
Run Code Online (Sandbox Code Playgroud)
并通过Luabind将它暴露给Lua,如下所示:
module(luaState)
[
class_<A>("Foo")
.def(constructor<>())
];
Run Code Online (Sandbox Code Playgroud)
最后在这样的脚本中实例化它:
A = Foo();
Run Code Online (Sandbox Code Playgroud)
那时A的实际"存在状态"是什么?
它是在堆中的某个地方,并且lua在某处保留了对它的引用?(或luabind ::对象?)
我觉得它只能是一个指针,如新的或同等的.
但是,我可以将函数绑定到接受引用的lua,例如lua_doSomething(A & a),最终会有一个实际的引用.诚然,我知道这很可能只是路过被luabind a的*a,但我不知道如果这是怎么回事了.
我问这个的原因是为了更好地理解和预测在脚本中实例化的对象的生命周期.
那个,我不确定所有权或生命周期是否会改变,如果不是像上面那样将类暴露给lua,我这样做:
A * lua_CreateA()
{
return new A();
}
module(luaState)
[
class_<A>("Foo")
];
module(luaState)
[
def("createA",&lua_CreateA)
];
Run Code Online (Sandbox Code Playgroud)
并使用它像
A = createA();
Run Code Online (Sandbox Code Playgroud)
根据我到目前为止所理解的逻辑,这个案例需要我进行清理,因为我是分配一个新对象的人,除非为luabind这样的赋值与使用绑定构造函数这样做.
简而言之,我真的很困惑对象的生命周期和这里的东西...我搜索与此相关的关键字,但我只是得到像http://www.gamedev.net/topic/525692-luabind这样的东西 -ownership和-破坏/
这不是我想知道的.我想了解在幕后处理有关分配,实例化,生命周期和所有这些事情的具体方法.
我正在使用Luabind将我的游戏引擎暴露给Lua.我最近遇到了麻烦,当我发现我无法在Lua中创建一个"新"例如GUIObject*obj = new GUIObject(),而在Lua中创建的所有内容都由Lua拥有.
那不是一个大问题我决定在对象上创建一种工厂模式,例如我的GUIManager Has
class GUIManager {
template <class T> T * CreateObject( T classType )
{
return new T();
}
}
Run Code Online (Sandbox Code Playgroud)
我的Luabind Bindings看起来像这样:
class_<GUIManager>("GUIManager")
.def("CreateObject", (GUILabel*(GUIManager::*)(GUILabel classType))&GUIManager::CreateObject<GUILabel>)
.def("CreateObject", (GUIImage*(GUIManager::*)(GUIImage classType))&GUIManager::CreateObject<GUIImage>)
Run Code Online (Sandbox Code Playgroud)
通过调用以下内容可以找到Lua的所有内容:
testLabel = theGUI:CreateObject(GUILabel())
Run Code Online (Sandbox Code Playgroud)
但是我觉得这不是"正确",因为我实际上是在创建一个传入的对象,我确信有一种更简单的方法,但到目前为止我尝试的所有其他方法都不同意编译器或Luabind.
如果需要,请随时询问更多信息
谢谢
我试图在Visual Studio 2010中使用Lua + Luabind制作一些HelloWorld.我从这里下载了Lua src 并将其源文件添加到项目中.然后我下载并添加了luabind的来源.最后添加了main.cpp.所以在那之后尝试编译项目并在大多数luabind文件中出错:
error C3861: 'lua_strlen': identifier not found
error C2065: 'LUA_GLOBALSINDEX' : undeclared identifier
Run Code Online (Sandbox Code Playgroud)
请帮帮我,我做错了什么?我必须在项目中添加哪些文件?也许一些额外的库?组织lua项目的最佳实践是什么?
c++ ×10
luabind ×10
lua ×9
allocation ×1
c++11 ×1
inheritance ×1
scripting ×1
shared-ptr ×1
templates ×1