From 16a3fa00177eb233b7c94cca237e6e33e7878789 Mon Sep 17 00:00:00 2001 From: Ryan Kelly Date: Fri, 19 Feb 2021 12:55:16 +1100 Subject: [PATCH] Get `cargo test py` passing on Windows. (#393) --- uniffi/src/testing.rs | 2 +- uniffi_bindgen/src/bindings/python/mod.rs | 9 +++++---- .../python/templates/NamespaceLibraryTemplate.py | 11 +++++++++-- .../src/bindings/python/templates/wrapper.py | 1 + 4 files changed, 16 insertions(+), 7 deletions(-) diff --git a/uniffi/src/testing.rs b/uniffi/src/testing.rs index a0babc7649..96dcdf4f25 100644 --- a/uniffi/src/testing.rs +++ b/uniffi/src/testing.rs @@ -121,7 +121,7 @@ pub fn ensure_compiled_cdylib(pkg_dir: &str) -> Result { .filenames .iter() .filter(|nm| match nm.extension().unwrap_or_default().to_str() { - Some("dylib") | Some("so") => true, + Some(std::env::consts::DLL_EXTENSION) => true, _ => false, }) .collect(); diff --git a/uniffi_bindgen/src/bindings/python/mod.rs b/uniffi_bindgen/src/bindings/python/mod.rs index 68412d89ca..cb6d9b35bb 100644 --- a/uniffi_bindgen/src/bindings/python/mod.rs +++ b/uniffi_bindgen/src/bindings/python/mod.rs @@ -57,12 +57,13 @@ pub fn generate_python_bindings(config: &Config, ci: &ComponentInterface) -> Res /// Execute the specifed python script, with environment based on the generated /// artifacts in the given output directory. pub fn run_script(out_dir: &Path, script_file: &Path) -> Result<()> { - let mut pythonpath = env::var_os("PYTHONPATH").unwrap_or_else(|| OsString::from("")); - // This lets python find the compiled library for the rust component. - pythonpath.push(":"); - pythonpath.push(out_dir); let mut cmd = Command::new("python3"); + // This helps python find the generated .py wrapper for rust component. + let pythonpath = env::var_os("PYTHONPATH").unwrap_or_else(|| OsString::from("")); + let pythonpath = + env::join_paths(env::split_paths(&pythonpath).chain(vec![out_dir.to_path_buf()]))?; cmd.env("PYTHONPATH", pythonpath); + // We should now be able to execute the tests successfully. cmd.arg(script_file); let status = cmd .spawn() diff --git a/uniffi_bindgen/src/bindings/python/templates/NamespaceLibraryTemplate.py b/uniffi_bindgen/src/bindings/python/templates/NamespaceLibraryTemplate.py index 7aa7a02896..a07508b107 100644 --- a/uniffi_bindgen/src/bindings/python/templates/NamespaceLibraryTemplate.py +++ b/uniffi_bindgen/src/bindings/python/templates/NamespaceLibraryTemplate.py @@ -11,7 +11,14 @@ def loadIndirect(): elif sys.platform == "darwin": libname = "lib{}.dylib" elif sys.platform.startswith("win"): - libname = "lib_{}.dll" + # As of python3.8, ctypes does not seem to search $PATH when loading DLLs. + # We could use `os.add_dll_directory` to configure the search path, but + # it doesn't feel right to mess with application-wide settings. Let's + # assume that the `.dll` is next to the `.py` file and load by full path. + libname = os.path.join( + os.path.dirname(__file__), + "{}.dll", + ) return getattr(ctypes.cdll, libname.format("{{ config.cdylib_name() }}")) # A ctypes library to expose the extern-C FFI definitions. @@ -23,4 +30,4 @@ def loadIndirect(): {%- call py::arg_list_ffi_decl(func) -%} ) _UniFFILib.{{ func.name() }}.restype = {% match func.return_type() %}{% when Some with (type_) %}{{ type_|type_ffi }}{% when None %}None{% endmatch %} -{%- endfor %} \ No newline at end of file +{%- endfor %} diff --git a/uniffi_bindgen/src/bindings/python/templates/wrapper.py b/uniffi_bindgen/src/bindings/python/templates/wrapper.py index f462604539..a936425eac 100644 --- a/uniffi_bindgen/src/bindings/python/templates/wrapper.py +++ b/uniffi_bindgen/src/bindings/python/templates/wrapper.py @@ -13,6 +13,7 @@ # compile the rust component. The easiest way to ensure this is to bundle the Python # helpers directly inline like we're doing here. +import os import sys import ctypes import enum