forked from mozilla/uniffi-rs
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Support foreign implementations of trait interfaces (mozilla#1578)
Scaffolding: * Generate a struct that implements the trait using a callback interface callback * Make `try_lift` input a callback interface handle and create one of those structs. * Don't use `try_lift` in the trait interface method scaffolding. `try_lift` expects to lift a callback handle, but scaffolding methods are called with a leaked object pointer. * Removed the unused RustCallStatus param from the callback initialization function Kotlin/Python/Swift: * Factored out the callback interface impl and interface/protocol templates so it can also be used for trait interfaces. * Changed the callback interface handle map code so that it doesn't try to re-use the handles. If an object is lowered twice, we now generate two different handles. This is required for trait interfaces, and I think it's also would be the right thing for callback interfaces if they could be passed back into the foreign language from Rust. * Make `lower()` return a callback interface handle. * Added some code to clarify how we generate the protocol and the implementation of that protocol for an object Other: * Trait interfaces are still not supported on Ruby. * Updated the coverall bindings tests to test this. * Updated the traits example, although there's definitely more room for improvement. TODO: I think a better handle solution (mozilla#1730) could help with a few things: * We're currently wrapping the object every time it's passed across the FFI. If the foreign code receives a trait object, then passes it back to Rust. Rust now has a handle to the foreign impl and that foreign impl just calls back into Rust. This can lead to some extremely inefficent FFI calls if an object is passed around enough. * The way we're coercing between pointers, usize, and uint64 is probably wrong and at the very least extremely brittle. There should be better tests for reference counts, but I'm waiting until we address the handle issue to implement them.
- Loading branch information
Showing
42 changed files
with
1,000 additions
and
532 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
import uniffi.traits.* | ||
|
||
for (button in getButtons()) { | ||
val name = button.name() | ||
// Check that the name is one of the expected values | ||
assert(name in listOf("go", "stop")) | ||
// Check that we can round-trip the button through Rust | ||
assert(press(button).name() == name) | ||
} | ||
|
||
// Test a button implemented in Kotlin | ||
class KtButton : Button { | ||
override fun name() = "KtButton" | ||
} | ||
|
||
assert(press(KtButton()).name() == "KtButton") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,15 @@ | ||
from traits import * | ||
|
||
for button in get_buttons(): | ||
if button.name() in ["go", "stop"]: | ||
press(button) | ||
else: | ||
print("unknown button", button) | ||
name = button.name() | ||
# Check that the name is one of the expected values | ||
assert(name in ["go", "stop"]) | ||
# Check that we can round-trip the button through Rust | ||
assert(press(button).name() == name) | ||
|
||
# Test a button implemented in Python | ||
class PyButton(Button): | ||
def name(self): | ||
return "PyButton" | ||
|
||
assert(press(PyButton()).name() == "PyButton") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
import traits | ||
|
||
for button in getButtons() { | ||
let name = button.name() | ||
// Check that the name is one of the expected values | ||
assert(["go", "stop"].contains(name)) | ||
// Check that we can round-trip the button through Rust | ||
assert(press(button: button).name() == name) | ||
} | ||
|
||
// Test a Button implemented in Swift | ||
class SwiftButton: Button { | ||
func name() -> String { | ||
return "SwiftButton" | ||
} | ||
} | ||
|
||
assert(press(button: SwiftButton()).name() == "SwiftButton") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,5 @@ | ||
uniffi::build_foreign_language_testcases!("tests/bindings/test_traits.py",); | ||
uniffi::build_foreign_language_testcases!( | ||
"tests/bindings/test_traits.py", | ||
"tests/bindings/test_traits.kts", | ||
"tests/bindings/test_traits.swift", | ||
); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.