C++ 在运行时使用C+中使用的脚本语言创建新类/成员+;

C++ 在运行时使用C+中使用的脚本语言创建新类/成员+;,c++,lua,swig,squirrel,C++,Lua,Swig,Squirrel,我断断续续地研究这个问题已经有几个月了,现在我真的想拿出一个合适的解决方案来处理在C++11项目的运行时使用成员函数/属性创建新的用户定义类(以及这些类的实例)的情况 到目前为止,我一直在使用SWIG(以前与Python一起使用,现在与Lua一起使用,探索Squirrel)。像我所遇到的所有C++绑定/嵌入库(Luna*,Luabter,LuabFin,OOLua,SqaDa/SqEXT,Surar)一样,所有的代码都希望在代码执行之前预定义C++类,因为它们要么依赖于预处理器指令或模板。 因此

我断断续续地研究这个问题已经有几个月了,现在我真的想拿出一个合适的解决方案来处理在C++11项目的运行时使用成员函数/属性创建新的用户定义类(以及这些类的实例)的情况

到目前为止,我一直在使用SWIG(以前与Python一起使用,现在与Lua一起使用,探索Squirrel)。像我所遇到的所有C++绑定/嵌入库(Luna*,Luabter,LuabFin,OOLua,SqaDa/SqEXT,Surar)一样,所有的代码都希望在代码执行之前预定义C++类,因为它们要么依赖于预处理器指令或模板。 因此,我的问题是,是否有任何库使用更程序化的方法包装语言,或者有任何关于Lua或Squirrel之类的好教程/示例,可以推荐用于处理使用自定义成员和函数的自定义命名类的创建?如能提供一些指导,将不胜感激

甚至简单地展示了一个很好的例子,说明如何用一个函数和一个属性创建一个自定义类,在Lua、SyrReR中,通过它们各自的C++ API,不使用宏/模板/动态生成的代码,将是非常有帮助的。 编辑:我已经创建了一个

实例
类,该类包含成员键/值对的
std::vector
,以及一个标识类型的成员,以便可以查找函数。然而,关于在Lua/Squirrel中创建简单类而不使用静态代码的文档很少


< >编辑2:我希望在任何平台上都能工作,而不必动态链接。< /P> < P>创建一个从现有C++类派生的类是我唯一的方法(把我自己)带进运行C++程序中。在动态编译实际C++源代码和加载生成的库时,物理上无法添加新的类。接下来最好的是在C++中创建一个代理对象,它包一个Python(Lua等)对象,并使该Python(Lua)对象成为一个类,该类扩展了一个现有的C++类,该类被镜像到Python(Lua)侧。

这是一个用Python扩展C++类的例子,使用Boosi::Python作为桥。 C++方面:

#include <boost/python.hpp>
#include <iostream>

using namespace boost::python;
// this is the interface we will implement in Python
struct World
{
    virtual std::string greet() = 0;
    virtual ~World() {}
};

// this is a helper class needed to access Python-overrided methods
struct WorldWrap : World, wrapper<World>
{
    std::string greet()
    {
        return this->get_override("greet")();
    }
};

// This function tests our class implemented in Python
std::string test(World* w)
{
    std::cout << "Calling w->greet() on some World-derived object\n";
    return w->greet();
}

// This is what the Python side will see
BOOST_PYTHON_MODULE(hello)
{
    class_<WorldWrap, boost::noncopyable>("World")
            .def("greet", pure_virtual(&World::greet));

    def("test", test);
}

考虑下面的Lua多重映射示例

Multimap={};
函数多重映射:\索引(键)
如果(键==“键”),则
本地ret={}
对于k,成对(自)do
ret[#ret+1]=k;
结束
返回ret;
其他的
返回rawget(getmetatable(self),键)
结束
结束
函数Multimap.Create()
局部自={};
可设置图元(自、多重映射);
回归自我;
结束
函数多重映射:插入(键、值)
本地列表=自[键];
如果(list==nil),则
列表={};
自[键]=列表;
结束
表.插入(列表、值);
结束
函数多重映射:删除(键、值)
本地列表=自[键];
断言(list~=nil,“找不到键”);
对于i=1,列出do
如果(列表[i]==值),则
表1.删除(列表一);
如果(#list==0),则
自[键]=零;
结束
返回;
结束
结束
错误(“未找到值”);
结束
--测试
m=Multimap.Create()
m:插入(1,5)
m:插入(2,6)
m:插入(3,7)
m:插入(1,8)
m:移除(2,6)
打印(pcall(函数()
m:Remove(2,6)——将产生断言异常
完)
打印(“键左:”,table.concat(m.keys,,'))

可以用C++实现这一点。

  • 使用重luaapi。下面的代码与Lua几乎完全相同
  • #包括
    int多重映射索引(lua\U状态*L){
    lua_settop(L,2);//强制2个参数
    常量字符*key\u value=“key”;
    大小键长度;
    const char*key=lua_tolstring(L、2和key_len);
    如果(!strncmp(key,key\u值,strlen(key\u值))){
    int i=0;
    lua_newtable(L);//堆栈:self,key,ret={}
    int-ret=lua_gettop(L);
    lua_pushnil(L);//堆栈:self,key,ret,nil
    while(lua_next(L,1)!=0){//stack:self,key,ret,k,v
    lua_pop(L,1);//堆栈:self,key,ret,k
    lua_len(L,ret);//堆栈:self,key,ret,k,#ret
    lua_pushvalue(L,-2);//堆栈:self,key,ret,k,#ret,k
    lua_rawseti(L,ret,lua_tointeger(L,-2)+1);//ret[#ret+1]=k;|堆栈:self,key,ret,k,#ret
    lua_pop(L,1);//堆栈:self,key,ret,k
    }
    //堆栈:self、key、ret
    返回1;
    }
    否则{
    lua_getmetatable(L,1);//堆栈:self,key,metatable(self)
    lua_pushvalue(L,2);//堆栈:self,key,元表(self),key
    lua_rawget(L,-2);//堆栈:self,key,metatable(self),rawget(metatable(self),key)
    返回1;
    }
    }
    int Multimap_Remove(lua_State*L){
    lua_settop(L,3);//强制3个参数:self、key、value
    lua_checkstack(L,12);//在堆栈上保留12个参数(以防万一)
    lua_pushvalue(L,2);//堆栈:self,key,value,key
    lua_gettable(L,1);//堆栈:self,key,value,list=self[key]
    if(lua_isnil(L,-1))
    luaL_错误(L,“未找到密钥”);
    lua_len(L,-1);//堆栈:self、key、value、list、#list
    整数计数=lua_tointeger(L,-1);
    lua_pop(L,1);//堆栈:self、key、value、list
    对于(inti=1;i免责声明:我将此贡献作为一个答案发布,因为我没有足够的声誉点数来添加评论

    注释:抛开与特定脚本语言绑定的问题不谈,您似乎面临着
    C++
    语言的一个基本限制:它不是“”(正如其他注释所指出的那样)。也就是说,语言d
    #include <boost/python.hpp>
    #include <iostream>
    
    using namespace boost::python;
    // this is the interface we will implement in Python
    struct World
    {
        virtual std::string greet() = 0;
        virtual ~World() {}
    };
    
    // this is a helper class needed to access Python-overrided methods
    struct WorldWrap : World, wrapper<World>
    {
        std::string greet()
        {
            return this->get_override("greet")();
        }
    };
    
    // This function tests our class implemented in Python
    std::string test(World* w)
    {
        std::cout << "Calling w->greet() on some World-derived object\n";
        return w->greet();
    }
    
    // This is what the Python side will see
    BOOST_PYTHON_MODULE(hello)
    {
        class_<WorldWrap, boost::noncopyable>("World")
                .def("greet", pure_virtual(&World::greet));
    
        def("test", test);
    }
    
    import hello
    
    
    class HomeWorld(hello.World):
        """ Implements a function defined in C++ as pure virtual """
        def greet(self):
            return "howdy"
    
    home = HomeWorld()
    print (hello.test(home))