Skip to content

Passing of non-POD types through FFI layers #77

Description

@aapoalas

A C++ function passing a class Foo instance by value may pass Foo equivalently to the C ABI if Foo was a C struct, or it might pass it by pointer. This is also dependent on the platform:

namespace lib {
class Foo {
  public:
  Foo();

  private:
  int data{0};
};

Foo createFoo();
}

This class gets passed through registers on SysV but is passed by-reference on MSVC. A function that returns Foo like createFoo needs to be called through a C++ shim to choose the ABI manually, or needs to have conditional compilation on the Rust side:

unsafe extern "C" {
  #[cfg_attr(windows, link_name = "?createFoo@lib@@")]
  #[cfg_attr(not(windows), link_name = "\u{1}_ZN3lib8createFooE")]
  #[cfg(windows)]
  fn createFoo(out: *mut Foo) -> *mut Foo;
  #[cfg(not(windows))]
  fn createFoo() -> Foo;
}

Tools can perform the shimming, or the conditional compilation. But fundamentally the ABI is a trait of the type, not of the function call. It might also be interesting for there to be a way to mark a Rust struct as non-POD - at least in the C ABI. The MSVC / SysV conditionality would then be fairly easy to implement with conditional marker fields.

Metadata

Metadata

Assignees

No one assigned

    Labels

    analysis-medUseful to analyse this issue furtherl-rustChanges that are mainly in Rustneeds-interopNeeds interop tool supportneeds-rustNeeds rust compiler or tooling changesp-semanticsLanguage semantics differencessolved-crubitSolved by Crubitsolved-cxxSolved by cxx (interop tool)t-problem-statementA description of an interop problem

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions