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

能否通过Sol3将Lua函数赋值给C++函数指针或std::function

这个需求完全可以实现,两种写法中std::function的方案是Sol3原生支持的,裸函数指针无法直接赋值,需要额外包装。

具体实现方式

1. 推荐方案:直接使用std::function存储

Sol3内置了对std::function的自动转换支持,只要你自定义的vec3类型提前在Sol3中完成注册,就可以直接赋值,不需要写额外的包装代码。
示例代码:

#include <sol/sol.hpp>
#include <functional>

// 假设vec3是你自定义的三维向量类型
struct vec3 {
    float x, y, z;
    vec3() : x(0), y(0), z(0) {}
    vec3(float x, float y, float z) : x(x), y(y), z(z) {}
};

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

    // 必须在获取Lua函数前注册自定义类型,否则Sol3无法完成参数/返回值转换
    lua.new_usertype<vec3>("vec3",
        sol::constructors<vec3(), vec3(float, float, float)>(),
        "x", &vec3::x,
        "y", &vec3::y,
        "z", &vec3::z
    );

    // 加载并执行Lua脚本,保证Idle.animate函数已经在Lua环境中定义
    lua.script(R"(
        Idle = {}
        function Idle.animate(a, b, c, pos)
            return vec3(pos.x + a, pos.y + b, pos.z + c)
        end
    )");

    // 直接赋值即可,Sol3自动完成类型适配
    std::function<vec3(float, float, float, vec3)> saved_script = lua["Idle"]["animate"];

    // 后续可以随时延迟调用,不需要持有Lua栈或者sol::state的额外引用
    vec3 result = saved_script(1.0f, 2.0f, 3.0f, vec3(0,0,0));
    return 0;
}

注意事项:

  • 存储的std::function生命周期不能超过对应的sol::state实例,否则调用时虚拟机已经销毁,会触发未定义行为
  • 如果Lua侧对应函数不存在、签名和std::function不匹配,赋值或调用时Sol3会抛出sol::error异常,按需做异常捕获即可
  • 如果不想使用异常,可以先将Lua函数存为sol::protected_function,再绑定到std::function,调用时可以手动处理错误

2. 不推荐方案:裸函数指针

你写的裸函数指针直接赋值的写法不可行。原因是Lua函数的执行依赖Lua虚拟机上下文,纯C裸函数指针不携带任何上下文状态,无法直接绑定到Lua侧的函数。
如果一定要用裸函数指针,只能通过全局/静态变量持有Lua状态和函数引用,再写一层静态包装函数:

// 全局持有Lua状态和函数引用,多虚拟机、多函数场景完全无法适配
sol::state* g_lua_ctx = nullptr;
sol::reference g_animate_ref = sol::lua_nil;

vec3 animate_wrapper(float a, float b, float c, vec3 pos) {
    return g_animate_ref.as<sol::protected_function>()(a, b, c, pos).get<vec3>();
}

// 初始化时手动绑定全局状态
g_lua_ctx = &lua;
g_animate_ref = lua["Idle"]["animate"];
// 之后才能拿到可用的裸函数指针
vec3 (*saved_script)(float, float, float, vec3) = animate_wrapper;

这种方案存在明显缺陷:依赖全局状态、无法支持多实例、需要手动管理引用生命周期,除非是老旧接口强制要求传裸函数指针,否则完全不建议使用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.03 10:06:36