-
Notifications
You must be signed in to change notification settings - Fork 238
[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
base: main
Are you sure you want to change the base?
Changes from all commits
f85d90a
1e4fd7e
21f224f
073633f
d6c8456
0e6bb12
df24e7b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1255,6 +1255,44 @@ object.doSomething() | |
// `object` will be released here. | ||
``` | ||
|
||
### Calling conventions when passing Shared Reference Types from Swift to C++ | ||
|
||
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++ | ||
fahadnayyar marked this conversation as resolved.
Show resolved
Hide resolved
|
||
void takeSharedObjectAsInout(SharedObject *& x) { ... } | ||
``` | ||
|
||
which would be imported in Swift as | ||
|
||
```swift | ||
fahadnayyar marked this conversation as resolved.
Show resolved
Hide resolved
|
||
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++. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 | ||
|
@@ -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 | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
TODO: ### -> ####