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

Can't figure out proper shim for UniquePtr instead of returning global singleton #1327

Open
n8henrie opened this issue Mar 18, 2024 · 0 comments

Comments

@n8henrie
Copy link

Hello,

I've long been interested in seeing of CXX could help in making rust bindings to TaskWarrior, though it looks like @djmitche is incorporating rust into the project in a different route (which is exciting to see) -- so this is mostly an experiment for my learning at this point.

I don't know C or C++, so I'm starting from a fairly disadvantaged perspective.

Using bindgen alone, I was able to get taskwarrior's Context::dispatch to work from Rust, so I wanted to convert my work (just a few lines of code) to CXX to compare.

TaskWarrior source

taskwarrior-sys (bindgen)

Hopefully my terminology is correct, but it seems that Taskwarrior uses this approach:

  • declares a uninitialized global Context (a singleton?)
  • Context::setContext (&globalContext);, which sets Context::context to the global context
  • Calls Context::getContext for all subsequent calls
  • Initializes the context
  • Calls Context::run, which delegates to Context::dispatch

To translate this to cxx, it looks like there may be a couple of challenges, for example regarding constructors:

Here is my attempt, with several lines commented out from previous attempts:

taskwarrior-sys (cxx)

The loop I would run into was, for example:

// static Context& Context::getContext ()
fn getContext() -> &Context;

Result: error: no member named 'getContext' in the global namespace

Doesn't work because this tries to define getContext as a free function and doesn't find the Context::getContext method. To fix that I need a self: parameter as noted in the issue above.

fn getContext(self: &Context) -> &Context;

result:

error: cannot initialize a variable of type 'const ::Context &(Context::*)() const' with an rvalue of type 'Context &(*)()': different return type ('const ::Context &' (aka 'const Context &') vs 'Context &')

Makes sense, I think this means that returning &Context returns a const value instead of a mutable one

  • Can't return &mut Context, must be Pin<&mut Context>
  • Can't return a Pin<&mut ...> without a Pin<&mut ...> input
fn getContext(self: Pin<&mut Context>) -> Pin<&mut Context>;

result:

error: cannot initialize a variable of type '::Context &(Context::*)()' with an rvalue of type 'Context &(*)()'

Unfortunately I don't really understand this, so then I tried creating a shim and creating / returning UniquePtr<Context>.

Am I on the right track just trying to create a shim that wraps everything in std::unique_ptr like so?

inline void Context_setContext(std::unique_ptr<Context> context) {
  Context::setContext(context);
}

Sorry that this is more of a "I don't know c++" problem than a rust problem; if there's a more appropriate place to ask, please let me know!

Thank you for your time and for providing this library!

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

1 participant