Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Is it possible to have out params / replace type and data referenced by sol::object? #1591

Open
shohnwal opened this issue Mar 25, 2024 · 2 comments

Comments

@shohnwal
Copy link

shohnwal commented Mar 25, 2024

Some programming languages offer the possibility of out-parameters, aka where the user can pass in arguments as reference to a function, inside the function the value gets modified via reference and once the function returns the value stays modified.

I can modify sol::objects content if they are already of the correct type, as I can just get an already correctly typed reference to their underlying value. however, what if the passed-in sol::object is of a different type, is it possible to replace the referred-to Lua value with a new object?

local u = MyUserType()
local n = nil
local v = 42
DoSomething(u)
DoSomething(n)
DoSomething(v)
--all three values should now be of type MyUserType
u:UserTypeFunc()
n:UserTypeFunc()
v:UserTypeFunc()
void DoSomething(sol::variadic_args args)
{
  sol::object obj = args[0];
  if(obj.is<MyUserType>())
  {
    MyUserType& data = obj.as<MyUserType&>();
    //modifyl MyUserType data
    //...
    //data obj refers to is now modified, as expected with an out-parameter, no issues here
  }
  else
  {
    // How to replace the type and data of whatever obj refers to with a new instance of MyUsertype?
    //for example, what if obj is referring to a number or nil, is it possible to replace that with a new 
    //instance of MyUserType? I can't just do 
    obj = sol::make_object<MyUserType>(...)
    //as it would only change what the obj in this scope would refer to, not what the input parameter 
    //in args or the variable in Lua refers to
  }
}

I know I can always use sol::variadic_results to return multiple values and do

local v = 42
v = DoSomething(v)
-- v is now userdata
sol::variadic_results DoSomething(sol::variadic_args args)
{
  sol::variadic_results results{};
  sol::object obj = args[0];
  if(obj.is<MyUserType>())
  {
    // do stuff with userdata and return it
    results.push_back(obj);
  }
  else
  {
     sol::object newUserData = ...
     results.push_back(newUserData);
  }
  return results;
}

but I was wondering whether it's possible to mimic out-parameters somehow, as it would be more consistent with what some people are used to with other languages.

By the way, thank you for this fantastic work. I have been using sol2 for years and I am very happy with it!

@Rochet2
Copy link

Rochet2 commented Mar 25, 2024

What you want to do in your example may be possible, but not exactly supported by lua.
You would need to use the debug library to replace the value of local variables.
See https://www.lua.org/manual/5.1/manual.html#pdf-debug.setlocal

For some alternative approaches see #1323 (comment)

@shohnwal
Copy link
Author

Oh, dumb me, I totally forgot that primitives get passed by value.
Never mind then, I'll just use the variadic_results approach then.

Thank you for the links! :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants