You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用sol2将C++抽象类接口暴露给Lua并实现调用?

在sol2中实现C++抽象类与Lua继承调用的方案

要在sol2中实现C抽象类接口并让Lua继承实现,核心思路是通过桥接类把Lua对象包装成符合C抽象类要求的实例——因为sol2无法直接绑定纯虚函数供Lua重写。以下是完整实现步骤:

1. C++端核心实现

定义抽象类loopable

class loopable {
public:
    virtual ~loopable() = default;
    virtual void loop() = 0; // 纯虚函数,定义接口规范
};

实现Lua桥接类

这个类继承自loopable,负责把C++的loop()调用转发到Lua对象的实现上:

#include <sol/sol.hpp>
#include <memory>
#include <vector>

class loopable_lua_bridge : public loopable {
private:
    sol::object m_lua_obj;
public:
    explicit loopable_lua_bridge(sol::object lua_obj) : m_lua_obj(std::move(lua_obj)) {}

    void loop() override {
        // 获取Lua对象的loop方法并调用,传入self参数以符合Lua面向对象语法
        sol::function loop_func = m_lua_obj["loop"];
        loop_func(m_lua_obj);
    }
};

修改engine类支持Lua对象

让engine的add_loopable支持两种重载:一种接收C++原生的loopable智能指针,另一种接收Lua对象并自动包装成桥接实例:

class engine {
private:
    std::vector<std::unique_ptr<loopable>> m_loopables;
public:
    // 接收C++实现的loopable实例
    void add_loopable(std::unique_ptr<loopable> obj) {
        m_loopables.push_back(std::move(obj));
    }

    // 接收Lua对象,自动创建桥接实例
    void add_loopable(sol::object lua_obj) {
        m_loopables.push_back(std::make_unique<loopable_lua_bridge>(std::move(lua_obj)));
    }

    void run() {
        for (auto& obj : m_loopables) {
            obj->loop(); // 统一调用接口,无需区分是C++还是Lua实现
        }
    }
};

2. sol2绑定代码

不需要把loopable绑定为usertype,只需暴露一个空表给Lua作为继承的"标记",保持Lua代码的原有写法:

int main() {
    sol::state lua;
    lua.open_libraries(sol::lib::base);

    // 暴露loopable空表,供Lua继承
    lua["loopable"] = sol::table();

    // 绑定engine类,需明确指定add_loopable的重载版本
    lua.new_usertype<engine>("engine",
        sol::constructors<engine()>(),
        "add_loopable", sol::overload(
            static_cast<void(engine::*)(std::unique_ptr<loopable>)>(&engine::add_loopable),
            static_cast<void(engine::*)(sol::object)>(&engine::add_loopable)
        ),
        "run", &engine::run
    );

    // 加载并执行Lua代码
    lua.script(R"(
        local Actor = setmetatable({}, {__index = loopable})

        function Actor:new()
            local obj = {}
            setmetatable(obj, self)
            self.__index = self
            return obj
        end

        function Actor:loop()
            print("Actor:loop")
        end

        local a = Actor:new()

        local e = engine:new()
        e:add_loopable(a)
        e:run()
    )");

    return 0;
}

关键说明

  • sol2不支持直接绑定纯虚函数让Lua重写,因为C纯虚函数要求必须有具体实现,桥接类相当于做了一层适配,把Lua的方法调用转成C能识别的接口。
  • 暴露空的loopable表给Lua,是为了让Lua代码保持原来的继承写法,无需修改业务逻辑。
  • add_loopable的重载设计让engine同时兼容C++原生实现和Lua实现的loopable实例。

内容的提问来源于stack exchange,提问作者Rodrigo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 07:14:58