Revision control
Copy as Markdown
Other Tools
{% if self.include_once_check("CallbackInterfaceRuntime.py") %}{% include "CallbackInterfaceRuntime.py" %}{% endif %}
{%- let trait_impl=format!("_UniffiTraitImpl{}", name) %}
# Put all the bits inside a class to keep the top-level namespace clean
class {{ trait_impl }}:
# For each method, generate a callback function to pass to Rust
{%- for (ffi_callback, meth) in vtable_methods.iter() %}
@{{ ffi_callback.name()|ffi_callback_name }}
def {{ meth.name() }}(
{%- for arg in ffi_callback.arguments() %}
{{ arg.name() }},
{%- endfor -%}
{%- if ffi_callback.has_rust_call_status_arg() %}
uniffi_call_status_ptr,
{%- endif %}
):
uniffi_obj = {{ ffi_converter_name }}._handle_map.get(uniffi_handle)
def make_call():
args = ({% for arg in meth.arguments() %}{{ arg|lift_fn }}({{ arg.name() }}), {% endfor %})
method = uniffi_obj.{{ meth.name() }}
return method(*args)
{% if !meth.is_async() %}
{%- match meth.return_type() %}
{%- when Some(return_type) %}
def write_return_value(v):
uniffi_out_return[0] = {{ return_type|lower_fn }}(v)
{%- when None %}
write_return_value = lambda v: None
{%- endmatch %}
{%- match meth.throws_type() %}
{%- when None %}
_uniffi_trait_interface_call(
uniffi_call_status_ptr.contents,
make_call,
write_return_value,
)
{%- when Some(error) %}
_uniffi_trait_interface_call_with_error(
uniffi_call_status_ptr.contents,
make_call,
write_return_value,
{{ error|type_name }},
{{ error|lower_fn }},
)
{%- endmatch %}
{%- else %}
def handle_success(return_value):
uniffi_future_callback(
uniffi_callback_data,
{{ meth.foreign_future_ffi_result_struct().name()|ffi_struct_name }}(
{%- match meth.return_type() %}
{%- when Some(return_type) %}
{{ return_type|lower_fn }}(return_value),
{%- when None %}
{%- endmatch %}
_UniffiRustCallStatus.default()
)
)
def handle_error(status_code, rust_buffer):
uniffi_future_callback(
uniffi_callback_data,
{{ meth.foreign_future_ffi_result_struct().name()|ffi_struct_name }}(
{%- match meth.return_type() %}
{%- when Some(return_type) %}
{{ meth.return_type().map(FfiType::from)|ffi_default_value }},
{%- when None %}
{%- endmatch %}
_UniffiRustCallStatus(status_code, rust_buffer),
)
)
{%- match meth.throws_type() %}
{%- when None %}
uniffi_out_return[0] = _uniffi_trait_interface_call_async(make_call, handle_success, handle_error)
{%- when Some(error) %}
uniffi_out_return[0] = _uniffi_trait_interface_call_async_with_error(make_call, handle_success, handle_error, {{ error|type_name }}, {{ error|lower_fn }})
{%- endmatch %}
{%- endif %}
{%- endfor %}
@{{ "CallbackInterfaceFree"|ffi_callback_name }}
def _uniffi_free(uniffi_handle):
{{ ffi_converter_name }}._handle_map.remove(uniffi_handle)
# Generate the FFI VTable. This has a field for each callback interface method.
_uniffi_vtable = {{ vtable|ffi_type_name }}(
{%- for (_, meth) in vtable_methods.iter() %}
{{ meth.name() }},
{%- endfor %}
_uniffi_free
)
# Send Rust a pointer to the VTable. Note: this means we need to keep the struct alive forever,
# or else bad things will happen when Rust tries to access it.
_UniffiLib.{{ ffi_init_callback.name() }}(ctypes.byref(_uniffi_vtable))