From c1c4a5ffa54ccf5c169615c1e363aea21e89247e Mon Sep 17 00:00:00 2001 From: Auke Willem Oosterhoff Date: Tue, 22 Dec 2020 11:20:52 +0100 Subject: [PATCH] readme/faq: document `rlib` crate type better --- README.md | 10 +++++----- guide/src/faq.md | 23 +++++++++++++++++++++++ src/lib.rs | 5 +++++ 3 files changed, 33 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index bfce81d5..27731e1f 100644 --- a/README.md +++ b/README.md @@ -45,6 +45,11 @@ edition = "2018" [lib] name = "string_sum" +# "cdylib" is necessary to produce a shared library for Python to import from. +# +# Downstream Rust code (including code in `bin/`, `examples/`, and `tests/`) will not be able +# to `use string_sum;` unless the "rlib" or "lib" crate type is also included, e.g.: +# crate-type = ["cdylib", "rlib"] crate-type = ["cdylib"] [dependencies.pyo3] @@ -91,11 +96,6 @@ rustflags = [ While developing, you can symlink (or copy) and rename the shared library from the target folder: On MacOS, rename `libstring_sum.dylib` to `string_sum.so`, on Windows `libstring_sum.dll` to `string_sum.pyd`, and on Linux `libstring_sum.so` to `string_sum.so`. Then open a Python shell in the same folder and you'll be able to `import string_sum`. -Adding the `cdylib` arguments in the `Cargo.toml` files changes the way your crate is compiled. -Other Rust projects using your crate will have to link against the `.so` or `.pyd` file rather than include your library directly as normal. -In order to make available your crate in the usual way for Rust user, you you might want to consider using both `crate-type = ["cdylib", "rlib"]` so that Rust users can use the `rlib` (the default lib crate type). -Another possibility is to create a new crate to perform the binding. - To build, test and publish your crate as a Python module, you can use [maturin](https://github.com/PyO3/maturin) or [setuptools-rust](https://github.com/PyO3/setuptools-rust). You can find an example for setuptools-rust in [examples/word-count](https://github.com/PyO3/pyo3/tree/master/examples/word-count), while maturin should work on your crate without any configuration. ## Using Python from Rust diff --git a/guide/src/faq.md b/guide/src/faq.md index 202daf99..1bda457f 100644 --- a/guide/src/faq.md +++ b/guide/src/faq.md @@ -28,6 +28,29 @@ extension-module = ["pyo3/extension-module"] default = ["extension-module"] ``` +## I can't run `cargo test`: my crate cannot be found for tests in `tests/` directory! + +The Rust book suggests to [put integration tests inside a `tests/` directory](https://doc.rust-lang.org/book/ch11-03-test-organization.html#integration-tests). + +For a PyO3 `extension-module` project where the `crate-type` is set to `"cdylib"` in your `Cargo.toml`, +the compiler won't be able to find your crate and will display errors such as `E0432` or `E0463`: + +``` +error[E0432]: unresolved import `my_crate` + --> tests/test_my_crate.rs:1:5 + | +1 | use my_crate; + | ^^^^^^^^^^^^ no external crate `my_crate` +``` + +The best solution is to make your crate types include both `rlib` and `cdylib`: + +``` +# Cargo.toml +[lib] +crate-type = ["cdylib", "rlib"] +``` + ## Ctrl-C doesn't do anything while my Rust code is executing! This is because Ctrl-C raises a SIGINT signal, which is handled by the calling Python process by simply setting a flag to action upon later. This flag isn't checked while Rust code called from Python is executing, only once control returns to the Python interpreter. diff --git a/src/lib.rs b/src/lib.rs index 41dce38c..55ea1c98 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -49,6 +49,11 @@ //! //! [lib] //! name = "string_sum" +//! # "cdylib" is necessary to produce a shared library for Python to import from. +//! # +//! # Downstream Rust code (including code in `bin/`, `examples/`, and `tests/`) will not be able +//! # to `use string_sum;` unless the "rlib" or "lib" crate type is also included, e.g.: +//! # crate-type = ["cdylib", "rlib"] //! crate-type = ["cdylib"] //! //! [dependencies.pyo3]