Skip to content

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

@n8henrie

Description

@n8henrie

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!

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions