I'm trying to use Lua scripts inside of my C++ application using sol library, but I have some problems with passing a C++ structure to Lua. My last attempt is that:
sol::state _interpreter;
_interpreter.open_libraries(sol::lib::base, sol::lib::math);
_interpreter.new_usertype<PriceData>
(
"PriceData",
sol::constructors<PriceData(PriceData pd)>(),
"best_bid", &PriceData::best_bid,
"best_ask", &PriceData::best_ask
);
std::string script = R"(
function check_condition(price_update)
print(price_update)
return true
end
)";
auto load_result = _interpreter.load(script);
if (!load_result.valid())
throw std::runtime_error(std::format("Failed to load condition inspector. Error: {}", sol::error{load_result}.what()));
auto f = load_result.get<sol::function>();
PriceData pd(106.0, 107.0);
f(pd)
The struct delcared like this.
struct PriceData
{
double best_bid = 0.0;
double best_ask = 0.0;
};
inline bool operator == (const PriceData& lhs, const PriceData& rhs)
{
return lhs.best_bid == rhs.best_bid && lhs.best_ask == rhs.best_ask;
}
I tried adding all of constructors to this struct in order to checkm if Lua just can't construct it, but unfourtunately nothing worked for me and i'm getting the same error every time.
[sol2] An error occurred and panic has been invoked: stack index 2, expected userdata, received no value: value is not a valid userdata
unknown file: Failure
C++ exception with description "lua: error: stack index 2, expected userdata, received no value: value is not a valid userdata " thrown in the test body.
What am i doing wrong?
sol::state::load
returns a result, this result contains a function (and it gladly implicitly converts to a function). calling this function only executes the script that was loaded.
std::string script = "print('hello')";
sol::function f = _interpreter.load(script);
f(); // prints hello
if the script declares a function, then executing this script will simply declare the function, you still need to get it from the interpreter state then call it.
std::string script = R"(
function check_condition(price_update)
print(price_update)
print("best bid = ", price_update.best_bid)
return true
end
)";
auto load_result = _interpreter.load(script);
if (!load_result.valid()) { /* throw something? */ }
sol::function f = load_result.get<sol::function>();
f(); // executes the script which declares a function
// get declared function
sol::function check_condition = _interpreter["check_condition"];
PriceData pd(106.0, 107.0);
bool call_return = check_condition(pd); // calls function
assert(call_return);
sol.PriceData*: 000001F00AC72F98
best bid = 106.0
your code for adding the usertype works.
_interpreter.new_usertype<PriceData>
(
"PriceData",
"best_bid", &PriceData::best_bid,
"best_ask", &PriceData::best_ask
);