Lua C API-从C++; 我尝试实例化并使用C++中的Lua类对象。 Lua类的定义如下 myclass = {} function myclass:new(o) o=o or {} setmetatable(o,self) self.__index=self return o end function myclass:init() self.something = 0 end function myclass:perform() self.something = self.something + 0.5 return performsomething(self.something) end 在C++中实例化对象,我做以下操作: lua_getglobal(L,"myclass"); lua_getfield(L, -1, "new"); lua_pcall(L,0,1,0); lua_newtable(L); lua_setglobal(L, "objname");
然后初始化:Lua C API-从C++; 我尝试实例化并使用C++中的Lua类对象。 Lua类的定义如下 myclass = {} function myclass:new(o) o=o or {} setmetatable(o,self) self.__index=self return o end function myclass:init() self.something = 0 end function myclass:perform() self.something = self.something + 0.5 return performsomething(self.something) end 在C++中实例化对象,我做以下操作: lua_getglobal(L,"myclass"); lua_getfield(L, -1, "new"); lua_pcall(L,0,1,0); lua_newtable(L); lua_setglobal(L, "objname");,c++,lua,lua-api,C++,Lua,Lua Api,然后初始化: lua_getglobal(L,"myclass"); lua_getfield(L, -1, "init"); lua_getglobal(L,"objname"); lua_pcall(L, 0, 0, 0); 然后执行: lua_getglobal(L, "myclass"); lua_getfield(L, -1, "perform"); lua_getglobal(L, "objname"); lua_pcall(L, 0, 1, 0); double res = lu
lua_getglobal(L,"myclass");
lua_getfield(L, -1, "init");
lua_getglobal(L,"objname");
lua_pcall(L, 0, 0, 0);
然后执行:
lua_getglobal(L, "myclass");
lua_getfield(L, -1, "perform");
lua_getglobal(L, "objname");
lua_pcall(L, 0, 1, 0);
double res = lua_tonumber(-1);
对于这个例子,我没有包括在需要时使用的lua\u pop()
方法
看来,通过指纹,我可以得到以下信息。已使用新方法成功实例化Lua对象。它也在init方法中成功初始化。但是,当调用perform方法时,self.something
member没有改变,它的值被设置为0,这似乎意味着我没有调用对象成员方法。我很确定我管理Lua堆栈以访问对象成员函数的方式有问题 是否有人已经处理过类似的案例,并且可以在这里提供帮助? 谢谢
Bests很可能您没有将
nargs
参数修改为lua\u pcall
函数
使用冒号语法(class:func()
)定义函数时,必须从C/C++端显式传递self
参数。在你的例子中没有这样的例子
只需对代码进行最低限度的更改,它将如下所示:
卢阿方面:
function performsomething(x)
print("type:", type(x))
print("value:", x)
return x
end
myclass = {}
function myclass:new(o)
o=o or {}
setmetatable(o,self)
self.__index=self
return o
end
function myclass:init()
self.something = 0
end
function myclass:perform()
self.something = self.something + 0.5
return performsomething(self.something)
end
C/C++端:
#include <stdio.h>
#include <lualib.h>
#include <lauxlib.h>
int main()
{
lua_State* L = luaL_newstate();
luaL_openlibs(L);
luaL_dofile(L, "myclass.lua");
// instantiate
lua_getglobal(L,"myclass");
lua_getfield(L, -1, "new");
lua_getglobal(L, "myclass");
lua_pcall(L,1,1,0);
lua_setglobal(L, "objname");
// init
lua_getglobal(L,"myclass");
lua_getfield(L, -1, "init");
lua_getglobal(L,"objname");
lua_pcall(L, 1, 0, 0);
// perform
lua_getglobal(L, "myclass");
lua_getfield(L, -1, "perform");
lua_getglobal(L, "objname");
lua_pcall(L, 1, 1, 0);
double res = lua_tonumber(L, -1);
printf("Result: %f\n", res);
lua_close(L);
return 0;
}
#包括
#包括
#包括
int main()
{
lua_State*L=luaL_newstate();
luaL_openlibs(L);
luaL_dofile(L,“myclass.lua”);
//实例化
lua_getglobal(L,“myclass”);
卢厄·格特菲尔德(L,-1,“新”);
lua_getglobal(L,“myclass”);
lua_pcall(L,1,1,0);
lua_setglobal(L,“objname”);
//初始化
lua_getglobal(L,“myclass”);
lua_getfield(L,-1,“init”);
lua_getglobal(L,“objname”);
lua_pcall(L,1,0,0);
//表演
lua_getglobal(L,“myclass”);
lua_getfield(L,-1,“执行”);
lua_getglobal(L,“objname”);
lua_pcall(L,1,1,0);
双精度=对数(L,-1);
printf(“结果:%f\n”,res);
卢厄关闭(L);
返回0;
}
很可能您没有将nargs
参数修改为lua\u pcall
函数
使用冒号语法(class:func()
)定义函数时,必须从C/C++端显式传递self
参数。在你的例子中没有这样的例子
只需对代码进行最低限度的更改,它将如下所示:
卢阿方面:
function performsomething(x)
print("type:", type(x))
print("value:", x)
return x
end
myclass = {}
function myclass:new(o)
o=o or {}
setmetatable(o,self)
self.__index=self
return o
end
function myclass:init()
self.something = 0
end
function myclass:perform()
self.something = self.something + 0.5
return performsomething(self.something)
end
C/C++端:
#include <stdio.h>
#include <lualib.h>
#include <lauxlib.h>
int main()
{
lua_State* L = luaL_newstate();
luaL_openlibs(L);
luaL_dofile(L, "myclass.lua");
// instantiate
lua_getglobal(L,"myclass");
lua_getfield(L, -1, "new");
lua_getglobal(L, "myclass");
lua_pcall(L,1,1,0);
lua_setglobal(L, "objname");
// init
lua_getglobal(L,"myclass");
lua_getfield(L, -1, "init");
lua_getglobal(L,"objname");
lua_pcall(L, 1, 0, 0);
// perform
lua_getglobal(L, "myclass");
lua_getfield(L, -1, "perform");
lua_getglobal(L, "objname");
lua_pcall(L, 1, 1, 0);
double res = lua_tonumber(L, -1);
printf("Result: %f\n", res);
lua_close(L);
return 0;
}
#包括
#包括
#包括
int main()
{
lua_State*L=luaL_newstate();
luaL_openlibs(L);
luaL_dofile(L,“myclass.lua”);
//实例化
lua_getglobal(L,“myclass”);
卢厄·格特菲尔德(L,-1,“新”);
lua_getglobal(L,“myclass”);
lua_pcall(L,1,1,0);
lua_setglobal(L,“objname”);
//初始化
lua_getglobal(L,“myclass”);
lua_getfield(L,-1,“init”);
lua_getglobal(L,“objname”);
lua_pcall(L,1,0,0);
//表演
lua_getglobal(L,“myclass”);
lua_getfield(L,-1,“执行”);
lua_getglobal(L,“objname”);
lua_pcall(L,1,1,0);
双精度=对数(L,-1);
printf(“结果:%f\n”,res);
卢厄关闭(L);
返回0;
}
在下面的例子中,我创建了C++中的一个简单类,可以使用LuaCAPI在Lua中使用。完成后,我想大部分内容超出了你的问题范围;不过,我希望我的解释和例子能有所帮助
<>当我使用Lua的C API创建<代码> USEDATABAS/COD>时,这就是我通常在C++中编写我的<代码>主< /C>函数的方法。在本例中,MyClass.h
是我为本例编写的简单类的头文件
#include <iostream>
#include <stdexcept>
#include <cstdio>
#include <cstdlib>
#include "MyClass.h"
extern "C" {
#include "lua.h"
#include "lualib.h"
#include "lauxlib.h"
}
int main(int argc, char** argv) {
// Check to make sure you have at least one .lua input file.
if (argc < 2) {
std::cerr << "Filename(s) expected from command line" << std::endl;
std::exit(EXIT_FAILURE);
}
// Try-catch block to handle any errors encountered when executing the Lua file(s).
try {
lua_State* L = luaL_newstate(L);
luaL_openlibs(L);
// Call a function to register Lua methods for `MyClass`; its declaration and definition are below.
lua_MyClass_register(L);
for (char** cpp = argv + 1; cpp < argv + argc; ++cpp) {
// Run the Lua script--provided as a command-line arg--and handle errors.
if (luaL_dofile(L, *cpp)) {
const char* err = lua_tostring(L, -1);
lua_close(L);
throw std::runtime_error(err);
}
}
lua_close(L);
} catch (const std::runtime_error &err) {
// Catch fatal errors from the Lua script and exit.
std::cerr << err.what() << std::endl;
std::exit(EXIT_FAILURE);
}
return 0;
}
下面是MyClass.h
对应的.cpp
文件:
#include "MyClass.h"
// These are the class member function definitions.
MyClass::MyClass(int something_in) {
something = something_in;
}
MyClass::~MyClass() {
}
void MyClass::set(int something_in) {
something = something_in;
return;
}
const int & MyClass::get() const {
return something;
}
// These are the definitions for the C functions that Lua will use to call the member functions.
// `MyClass` constructor, which corresponds to `MyClass.new` in Lua.
int lua_MyClass_new(lua_State* L) {
// Optional argument to supply to the `MyClass` constructor; using `luaL_optinteger`, it defaults to 0.
int something_in = static_cast<int>(luaL_optinteger(L, 1, 0));
MyClass** mcpp = reinterpret_cast<MyClass**>(lua_newuserdata(L, sizeof(MyClass**)));
*mcpp = new MyClass(something_in);
luaL_setmetatable(L, LUA_MYCLASS);
return 1;
}
// `MyClass` destructor, which corresponds to the `__gc` metamethod in Lua.
int lua_MyClass_delete(lua_State* L) {
MyClass* mcp = *reinterpret_cast<MyClass**>(luaL_checkudata(L, 1, LUA_MYCLASS));
delete mcp;
return 0;
}
// C function corresponding to `MyClass::set`.
int lua_MyClass_set(lua_State* L) {
MyClass* mcp = *reinterpret_cast<MyClass**>(luaL_checkudata(L, 1, LUA_MYCLASS));
int something_in = static_cast<int>(luaL_checkinteger(L, 2));
mcp->set(something_in);
return 0;
}
// C function corresponding to `MyClass::get`.
int lua_MyClass_get(lua_State* L) {
MyClass* mcp = *reinterpret_cast<MyClass**>(luaL_checkudata(L, 1, LUA_MYCLASS));
lua_pushinteger(L, mcp->get());
return 1;
}
// `__newindex` metamethod for `MyClass` userdata that prevents any members from being added.
int lua_MyClass_newindex(lua_State* L) {
return luaL_error(L, "attempt to modify a read-only object");
}
// `__newindex` metamethod for the `MyClass` table that prevents any methods from being added--I will explain more below.
int lua_MyClass_table_newindex(lua_State* L) {
return luaL_error(L, "attempt to modify a read-only table");
}
// Function to register all the above functions for use in Lua; this gets called in `main.cpp`.
void lua_MyClass_register(lua_State* L) {
// Create a global table that will contain all the `MyClass` methods as functions.
// Include `lua_MyClass_new` as a constructor in the form `MyClass.new`.
lua_newtable(L);
lua_pushcfunction(L, lua_MyClass_new);
lua_setfield(L, -2, "new");
// Include `MyClass::get` and `MyClass::set` in this table as well.
luaL_setfuncs(L, MyClass_methods, 0);
// Create a metatable for the global table `MyClass`--which was just created.
lua_newtable(L);
// Prevent access to the metatable.
lua_pushliteral(L, "metatable");
lua_setfield(L, -2, "__metatable");
lua_pushcfunction(L, lua_MyClass_table_newindex);
lua_setfield(L, -2, "__newindex");
// Set this second table as the metatable for the one created above.
lua_setmetatable(L, -2);
// Call the first table "MyClass" and add it to the global environment table (_ENV).
lua_setglobal(L, LUA_MYCLASS);
// Create a metatable to be used by `MyClass` objects--this is different from the above tables because it will not contain the `new` method.
luaL_newmetatable(L, LUA_MYCLASS);
// Same as before, lock the metatable.
lua_pushliteral(L, "metatable");
lua_setfield(L, -2, "__metatable");
// Add metamethods contained in the `luaL_Reg` struct `MyClass_metamethods`.
luaL_setfuncs(L, MyClass_metamethods, 0);
// Create an index--the `__index` metamethod--for the above table to use for `MyClass` objects.
lua_newtable(L);
// Add methods.
luaL_setfuncs(L, MyClass_methods, 0);
lua_setfield(L, -2, "__index");
// This pop operation is probably unnecessary since the Lua stack should be cleaned up when this function returns.
lua_pop(L, 1);
return;
}
这将输出以下内容:
0
5
6
函数lua_MyClass_register
的定义非常复杂,需要创建许多表。我这样写是因为我想创建一个全局表,其中包含MyClass
构造函数和方法,其形式与Lua中的全局string
表相同。以函数string.match
为例:它可以作为函数调用,就像string.match(str,pattern)
一样;或者,它可以作为方法调用,如str:match(pattern)
。我注册了<代码> MyClass < /COD>所有函数的方式允许这种行为,除了全局表<代码> MyClass < /C>还包含构造函数,而类型< >代码> MyClass < /C>不。 < P>在下面的示例中,我创建了C++中的一个简单类,可以使用LuaCAPI在Lua中使用。完成后,我想大部分内容超出了你的问题范围;不过,我希望我的解释和例子能有所帮助
<>当我使用Lua的C API创建<代码> USEDATABAS/COD>时,这就是我通常在C++中编写我的<代码>主< /C>函数的方法。在本例中,MyClass.h
是我为本例编写的简单类的头文件
#include <iostream>
#include <stdexcept>
#include <cstdio>
#include <cstdlib>
#include "MyClass.h"
extern "C" {
#include "lua.h"
#include "lualib.h"
#include "lauxlib.h"
}
int main(int argc, char** argv) {
// Check to make sure you have at least one .lua input file.
if (argc < 2) {
std::cerr << "Filename(s) expected from command line" << std::endl;
std::exit(EXIT_FAILURE);
}
// Try-catch block to handle any errors encountered when executing the Lua file(s).
try {
lua_State* L = luaL_newstate(L);
luaL_openlibs(L);
// Call a function to register Lua methods for `MyClass`; its declaration and definition are below.
lua_MyClass_register(L);
for (char** cpp = argv + 1; cpp < argv + argc; ++cpp) {
// Run the Lua script--provided as a command-line arg--and handle errors.
if (luaL_dofile(L, *cpp)) {
const char* err = lua_tostring(L, -1);
lua_close(L);
throw std::runtime_error(err);
}
}
lua_close(L);
} catch (const std::runtime_error &err) {
// Catch fatal errors from the Lua script and exit.
std::cerr << err.what() << std::endl;
std::exit(EXIT_FAILURE);
}
return 0;
}
下面是MyClass.h
对应的.cpp
文件:
#include "MyClass.h"
// These are the class member function definitions.
MyClass::MyClass(int something_in) {
something = something_in;
}
MyClass::~MyClass() {
}
void MyClass::set(int something_in) {
something = something_in;
return;
}
const int & MyClass::get() const {
return something;
}
// These are the definitions for the C functions that Lua will use to call the member functions.
// `MyClass` constructor, which corresponds to `MyClass.new` in Lua.
int lua_MyClass_new(lua_State* L) {
// Optional argument to supply to the `MyClass` constructor; using `luaL_optinteger`, it defaults to 0.
int something_in = static_cast<int>(luaL_optinteger(L, 1, 0));
MyClass** mcpp = reinterpret_cast<MyClass**>(lua_newuserdata(L, sizeof(MyClass**)));
*mcpp = new MyClass(something_in);
luaL_setmetatable(L, LUA_MYCLASS);
return 1;
}
// `MyClass` destructor, which corresponds to the `__gc` metamethod in Lua.
int lua_MyClass_delete(lua_State* L) {
MyClass* mcp = *reinterpret_cast<MyClass**>(luaL_checkudata(L, 1, LUA_MYCLASS));
delete mcp;
return 0;
}
// C function corresponding to `MyClass::set`.
int lua_MyClass_set(lua_State* L) {
MyClass* mcp = *reinterpret_cast<MyClass**>(luaL_checkudata(L, 1, LUA_MYCLASS));
int something_in = static_cast<int>(luaL_checkinteger(L, 2));
mcp->set(something_in);
return 0;
}
// C function corresponding to `MyClass::get`.
int lua_MyClass_get(lua_State* L) {
MyClass* mcp = *reinterpret_cast<MyClass**>(luaL_checkudata(L, 1, LUA_MYCLASS));
lua_pushinteger(L, mcp->get());
return 1;
}
// `__newindex` metamethod for `MyClass` userdata that prevents any members from being added.
int lua_MyClass_newindex(lua_State* L) {
return luaL_error(L, "attempt to modify a read-only object");
}
// `__newindex` metamethod for the `MyClass` table that prevents any methods from being added--I will explain more below.
int lua_MyClass_table_newindex(lua_State* L) {
return luaL_error(L, "attempt to modify a read-only table");
}
// Function to register all the above functions for use in Lua; this gets called in `main.cpp`.
void lua_MyClass_register(lua_State* L) {
// Create a global table that will contain all the `MyClass` methods as functions.
// Include `lua_MyClass_new` as a constructor in the form `MyClass.new`.
lua_newtable(L);
lua_pushcfunction(L, lua_MyClass_new);
lua_setfield(L, -2, "new");
// Include `MyClass::get` and `MyClass::set` in this table as well.
luaL_setfuncs(L, MyClass_methods, 0);
// Create a metatable for the global table `MyClass`--which was just created.
lua_newtable(L);
// Prevent access to the metatable.
lua_pushliteral(L, "metatable");
lua_setfield(L, -2, "__metatable");
lua_pushcfunction(L, lua_MyClass_table_newindex);
lua_setfield(L, -2, "__newindex");
// Set this second table as the metatable for the one created above.
lua_setmetatable(L, -2);
// Call the first table "MyClass" and add it to the global environment table (_ENV).
lua_setglobal(L, LUA_MYCLASS);
// Create a metatable to be used by `MyClass` objects--this is different from the above tables because it will not contain the `new` method.
luaL_newmetatable(L, LUA_MYCLASS);
// Same as before, lock the metatable.
lua_pushliteral(L, "metatable");
lua_setfield(L, -2, "__metatable");
// Add metamethods contained in the `luaL_Reg` struct `MyClass_metamethods`.
luaL_setfuncs(L, MyClass_metamethods, 0);
// Create an index--the `__index` metamethod--for the above table to use for `MyClass` objects.
lua_newtable(L);
// Add methods.
luaL_setfuncs(L, MyClass_methods, 0);
lua_setfield(L, -2, "__index");
// This pop operation is probably unnecessary since the Lua stack should be cleaned up when this function returns.
lua_pop(L, 1);
return;
}
这将输出以下内容:
0
5
6
函数lua_MyClass_register
的定义非常复杂,需要创建许多表。我这样写是因为我想创建一个全局表,其中包含MyClass
构造函数和方法,其形式与Lua中的全局string
表相同。以函数string.match
为例:它可以作为函数调用,就像string.match(str,pattern)
一样;或者,它可以作为方法调用,如str:match(pattern)
。我为MyClass
注册所有函数的方式允许这种行为,但全局表MyClass
也包含构造函数,而MyClass
类型的对象不包含构造函数。我不确定该怎么做。对不起,我的第一条评论是错误的。