Skip to content

Commit 04bb606

Browse files
committed
[cxx-interop] Document guarantees and assumptions for non-const C++ shared references passed to a C++ API from Swift
1 parent 823cbca commit 04bb606

File tree

1 file changed

+39
-1
lines changed

1 file changed

+39
-1
lines changed

documentation/cxx-interop/index.md

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1322,6 +1322,44 @@ unOwned.doSomething()
13221322
Note that the Swift compiler will automatically infer the ownership conventons for Swift functions returning `SWIFT_SHARED_REFERENCE` types.
13231323
See [Exposing C++ Shared Reference Types back from Swift](#exposing-c-shared-reference-types-back-from-swift) for calling Swift functions returning `SWIFT_SHARED_REFERENCE` types from C++.
13241324

1325+
### Calling conventions when passing Shared Reference Types from Swift to C++
1326+
1327+
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.
1328+
Swift also retains the ownership of the value.
1329+
In other words, the argument is passed at `+0` and there is no transfer of ownership.
1330+
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.
1331+
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.
1332+
1333+
1334+
```swift
1335+
var obj = SharedObject.create()
1336+
receiveSharedObject(obj) // Swift guarantees that obj is alive and it is passed at +0
1337+
```
1338+
1339+
```c++
1340+
void receiveSharedObject(SharedObject *sobj) {
1341+
...
1342+
// Swift assumes that sobj is a valid, non-null object at the end of this function
1343+
}
1344+
```
1345+
1346+
Note that if the argument is an inout (non-const reference) as shown below:
1347+
1348+
```c++
1349+
void takeSharedObjectAsInout(SharedObject *& x) { ... }
1350+
```
1351+
1352+
which would be imported in Swift as
1353+
1354+
```swift
1355+
func takeSharedObjectAsInout(_ x: inout SharedObject) { ... }
1356+
```
1357+
1358+
The C++ function can overwrite the value of the argument with the new value.
1359+
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.
1360+
Adhering to these rules is necessary to safely and correctly pass around `SWIFT_SHARED_REFERENCE` between Swift and C++.
1361+
These rules are also generally recommended conventions to manage shared objects that use reference counting.
1362+
13251363
### Inheritance and Virtual Member Functions
13261364

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

1333-
#### Exposing C++ Shared Reference Types back from Swift
1371+
### Exposing C++ Shared Reference Types back from Swift
13341372

13351373
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,
13361374
but their references can be passed back and forth between Swift and C++. This section explains the conventions of incrementing and decrementing

0 commit comments

Comments
 (0)