Skip to content

[cxx-interop] Document guarantees and assumptions for SWIFT_SHARED_REFERENCE types passed to a C++ API as a parameter from Swift #816

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

Open
wants to merge 7 commits into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 39 additions & 1 deletion documentation/cxx-interop/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -1255,6 +1255,44 @@ object.doSomething()
// `object` will be released here.
```

### Calling conventions when passing Shared Reference Types from Swift to C++
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TODO: ### -> ####


If a C++ shared reference type is passed as an argument to a C++ API from Swift, the Swift compiler guarantees that the passed value would be alive.
Swift also retains the ownership of the value.
In other words, the argument is passed at `+0` and there is no transfer of ownership.
The C++ function should not assume that it has the ownership of the value and should do necessary retain operations if it is needs to take ownership.
The C++ function is responsible for ensuring that the value pointed to by the parameter is alive during and at the end of the function call.


```swift
var obj = SharedObject.create()
receiveSharedObject(obj) // Swift guarantees that obj is alive and it is passed at +0
```

```c++
void receiveSharedObject(SharedObject *sobj) {
...
// Swift assumes that sobj is a valid, non-null object at the end of this function
}
```

Note that if the argument is an inout (non-const reference) as shown below:

```c++
void takeSharedObjectAsInout(SharedObject *& x) { ... }
```

which would be imported in Swift as

```swift
func takeSharedObjectAsInout(_ x: inout SharedObject) { ... }
```

The C++ function can overwrite the value of the argument with the new value.
However, the C++ function is responsible for releasing the old value, and ensuring that the new value is properly retained so that the Swift caller has ownership of the new value when the function returns.
Adhering to these rules is necessary to safely and correctly pass around `SWIFT_SHARED_REFERENCE` between Swift and C++.
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@j-hui these 2 last lines are good, but I am not sure about their placement. Any suggestions?

Since we are editing this document with multiple calling conventions and rules about safely using SWIFT_SHARED_REFERENCE types and passing across the boundaries, I am not sure where to place these 2 lines.

Or maybe we can do such minor palcement edits later in a follow up patch?

These rules are also generally recommended conventions to manage shared objects that use reference counting.

### Inheritance and Virtual Member Functions

Similar to value types, casting an instance of a derived reference type to a
Expand All @@ -1263,7 +1301,7 @@ base reference type, or vice versa, is not yet supported by Swift.
If a reference type has virtual methods, you can call those methods from Swift.
This includes pure virtual methods.

#### Exposing C++ Shared Reference Types back from Swift
### Exposing C++ Shared Reference Types back from Swift

C++ can call into Swift APIs that take or return C++ Shared Reference Types. Objects of these types are always created on the C++ side,
but their references can be passed back and forth between Swift and C++. This section explains the conventions of incrementing and decrementing
Expand Down