Open akovachev opened 7 months ago
Would something like this work for you?
#define SOL_ALL_SAFETIES_ON 1
#include <sol/sol.hpp>
struct Cpp {
};
int main() {
sol::state lua;
lua.open_libraries(sol::lib::base, sol::lib::package);
auto cpp_meta = lua.new_usertype<Cpp>("Cpp");
lua.script(R"(
Cpp.memberFunc = function(...)
print(...)
end
cpp = Cpp.new()
cpp:memberFunc("hello world!")
-- prints sol.Cpp: 0x5b0038 hello world!
)");
return 0;
}
Its not what you ask, but it achieves what you set out to do in your code example from what I see.
@Rochet2 Thank you for your suggestion.
However the goal is cpp:memberFunction to be called from the C++ class such that the Lua implementation has access to the Lua self table. I know I can pass in the C++ this pointer but that won’t ensure access to the self object.
On Sun, Dec 3, 2023 at 12:30 PM Rochet2 @.***> wrote:
Would something like this work for you?
define SOL_ALL_SAFETIES_ON 1
include <sol/sol.hpp>
struct Cpp { }; int main() { sol::state lua; lua.open_libraries(sol::lib::base, sol::lib::package);
auto cpp_meta = lua.new_usertype<Cpp>("Cpp"); lua.script(R"( Cpp.memberFunc = function(...) print(...) end cpp = Cpp.new() cpp:memberFunc("hello world!") )"); return 0;
}
Its not what you ask, but it achieves what you set out to do in your code example from what I see.
— Reply to this email directly, view it on GitHub https://github.com/ThePhD/sol2/issues/1559#issuecomment-1837436914, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAZKSUCE2KYGS4NUDHAOLHTYHRIFDAVCNFSM6AAAAABAEUFCKWVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMYTQMZXGQZTMOJRGQ . You are receiving this because you authored the thread.Message ID: @.***>
In short I need something like returns_self
, but instead of returning it, for it to be passed in as sol::object or sol::reference to a bound member function.
Attaching one of the tests using returns_self
from sol::policies
:
TEST_CASE("policies/self", "ensure we return a direct reference to the lua userdata rather than creating a new one") {
struct vec2 {
float x = 20.f;
float y = 20.f;
vec2& normalize() {
float len2 = x * x + y * y;
if (len2 != 0) {
float len = sqrtf(len2);
x /= len;
y /= len;
}
return *this;
}
~vec2() {
x = std::numeric_limits<float>::lowest();
y = std::numeric_limits<float>::lowest();
}
};
sol::state lua;
lua.open_libraries(sol::lib::base);
lua.new_usertype<vec2>("vec2", "x", &vec2::x, "y", &vec2::y, "normalize", sol::policies(&vec2::normalize, sol::returns_self()));
auto result1 = lua.safe_script(R"(
v1 = vec2.new()
print('v1:', v1.x, v1.y)
v2 = v1:normalize()
print('v1:', v1.x, v1.y)
print('v2:', v2.x, v2.y)
print(v1, v2)
assert(rawequal(v1, v2))
v1 = nil
collectgarbage()
print(v2) -- v2 points to same, is not destroyed
)",
sol::script_pass_on_error);
REQUIRE(result1.valid());
}
I think I found the solution, it's not super obvious, but there is a working example:
https://github.com/ThePhD/sol2/blob/develop/examples/source/self_from_lua.cpp
The key is to dig inside the state's stack using this_state (from the example above):
thing(sol::this_state ts) {
lua_State* L = ts;
// references the object that called this function
// in constructors:
sol::stack_object selfobj(L, 1);
// definitely the same
thing& self = selfobj.as<thing>();
SOL_ASSERT(&self == this);
}
void func(sol::this_state ts) const {
lua_State* L = ts;
// references the object that called this function
// in regular member functions:
sol::stack_object selfobj(L, 1);
// "1" is the bottom of the Lua stack
// 2 is one up, so on and so forth...
thing& self = selfobj.as<thing>();
// definitely the same
SOL_ASSERT(&self == this);
}
I need to call a Lua function attached to the object instance from C++ class member function.
In other words I need to pass the self object to the function when calling from C++. If I know the name of the object I can access it by state["objectName"] and pass it. But unless I cache it somewhere I can't really convert this pointer to self object. I'm looking for an elegant mechanism to do this as I have a ton of bound C++ classes that need to call custom functions.
Ideally I'd want to do this at construction time. Perhaps by getting access to the Lua table object as a constructor parameter? Would that even work, or is the table created after the object has been constructed?
class Cpp { public: ... void callLuaMemberFunction { if (luaMemberFunc) { luaMemberFunc(, params...);
}
}
void bindLuaFunction(const std::string& key, sol::function func) { if (key == "memberFunc") { luaMemberFunc = std::move(func); } // ... [Handle other overridable functions similarly] }
private: sol::function luaMemberFunc; }
at binding time:
cpp.set(sol::meta_function::new_index, [](Cpp& _this, const std::string& key, sol::function func) { _this.bindLuaFunction(key, func); });
Lua:
cpp = Cpp() cpp:memberFunc = function(...) end
Currently I'm solving this by passing the name to the object at construction which then looks up the object by name every call. A typo could be an issue if we pass a different name than the object's assigned name. Something I'd like to avoid. I also want to avoid caching the object for each Lua member function (I'm assuming I'd have access to it at new_index call).