Rust는 안전성, 속도 및 병렬성을 고려한 시스템 프로그래밍 언어입니다. Rust는 C/C++보다 안정성 면에서 우수하며, 파이썬의 프로젝트에서도 유용하게 사용될 수 있습니다. PyO3는 Rust를 이용하여 만든 파이썬 확장을 작성할 수 있는 라이브러리입니다. 이 블로그 포스트에서는 Rust와 PyO3를 사용하여 파이썬에서 C/C++ 라이브러리를 호출하는 방법에 대해 알아보겠습니다.
1. Rust 프로젝트 생성하기
Rust로 C/C++ 라이브러리를 호출하기 위해서는 Rust 프로젝트를 먼저 생성해야 합니다. 다음은 Rust 프로젝트를 생성하는 명령어입니다.
$ cargo new my_project
위 명령어를 실행하면 my_project
라는 이름의 Rust 프로젝트가 생성됩니다.
2. PyO3 설치하기
PyO3를 설치하기 위해서는 해당 프로젝트의 Cargo.toml
파일에 PyO3 종속성을 추가해야 합니다. 다음은 Cargo.toml
파일에 PyO3 종속성을 추가하는 예시입니다.
[dependencies]
pyo3 = { version = "0.15", features = ["extension-module"] }
위와 같이 Cargo.toml
파일에 종속성을 추가한 후, 다음 명령어를 실행하여 PyO3를 설치합니다.
$ cargo build
3. Rust 코드 작성하기
Rust로 C/C++ 라이브러리를 호출하기 위해서는 Rust 코드를 작성해야 합니다. 다음은 Rust 프로젝트의 src/lib.rs
파일에 Rust 코드를 작성하는 예시입니다.
use pyo3::prelude::*;
#[pymodule]
fn my_module(py: Python, m: &PyModule) -> PyResult<()> {
// C/C++ 라이브러리 호출 코드 작성
// ...
Ok(())
}
#[pymodule]
fn rust_library(_py: Python, m: &PyModule) -> PyResult<()> {
m.add_module::<my_module>()?;
Ok(())
}
#[pymodule]
fn my_project(_py: Python, m: &PyModule) -> PyResult<()> {
m.add_module::<rust_library>()?;
Ok(())
}
#[pymodule]
fn my_library_py(_py: Python, m: &PyModule) -> PyResult<()> {
m.add_module::<my_project>()?;
Ok(())
}
#[pymodule]
fn my_library(_py: Python, m: &PyModule) -> PyResult<()> {
m.add_module::<my_library_py>()?;
Ok(())
}
// PyO3 모듈 초기화
#[pymodule]
fn my_library_rust(_py: Python, m: &PyModule) -> PyResult<()> {
m.add_module::<my_library>()?;
Ok(())
}
#[pymodule]
fn _my_library(_py: Python, m: &PyModule) -> PyResult<()> {
m.add_module::<my_library_rust>()?;
Ok(())
}
#[pymodule]
fn my_library_pybynative(_py: Python, m: &PyModule) -> PyResult<()> {
m.add("my_native_function", py_fn!(my_native_function))?;
Ok(())
}
#[pymodule]
fn my_library_native(_py: Python, m: &PyModule) -> PyResult<()> {
m.add_module::<my_library_pybynative>()?;
Ok(())
}
#[pymodule]
fn _my_library_native(_py: Python, m: &PyModule) -> PyResult<()> {
m.add_module::<my_library_native>()?;
Ok(())
}
/// Python에서 호출할 함수
#[pyfunction]
fn my_native_function(_py: Python, arg: usize) -> usize {
// C/C++ 라이브러리 호출 함수 정의
// ...
arg * 2
}
/// Rust에서 파이썬 확장 모듈을 생성하는 함수
#[pymodule]
fn my_extension_module(py: Python, m: &PyModule) -> PyResult<()> {
m.add_function(wrap_pyfunction!(my_native_function, m)?)?;
Ok(())
}
/// PyO3 초기화 함수
#[pymodule]
fn my_module_initializer(py: Python, m: &PyModule) -> PyResult<()> {
m.add_function(wrap_pyfunction!(my_extension_module, m)?)?;
Ok(())
}
/// PyO3 모듈 정의
#[pyclass(subclass)]
#[derive(Debug)]
struct MyModule {}
#[pymethods]
impl MyModule {
#[new]
#[args(kwargs = "**")]
fn new(kwargs: Option<&PyDict>) -> PyResult<Self> {
let wrap = Python::with_gil(|py| {
my_module_initializer(py, m)?;
my_module.weather_init()?;
my_module.rust_library_init()?;
my_module.my_module_init()?;
my_module.my_project_init()?;
my_module.my_library_init()?;
my_module.my_library_py_init()?;
my_module.my_library_rust_init()?;
my_module._my_library_init()?;
my_module.my_library_native_init()?;
my_module._my_library_native_init()?;
my_module.my_library_pybynative_init()?;
Ok(())
});
Ok(Self { py_module: wrap })
}
}
/// 모듈 초기화 함수
#[no_mangle]
pub extern "C" fn PyInit_my_module() -> *mut pyo3::ffi::PyObject {
let wrap = pyo3::types::IntoPy::into_py(Some(pyo3::types::Borrow::Borrowed(Python::acquire_gil().python())), pyo3::types::PyAny::new(MyModule::new(None).unwrap())) as *mut pyo3::ffi::PyObject;
wrap
}
위 코드는 Rust로 작성된 C/C++ 라이브러리를 호출하기 위한 예시 코드입니다. 필요한 C/C++ 라이브러리 호출 코드를 작성해 주세요.
4. PyO3를 이용한 라이브러리 호출
Rust 코드가 작성되었다면, PyO3를 사용하여 파이썬에서 Rust 코드를 호출할 수 있습니다. 다음은 파이썬에서 Rust 라이브러리를 호출하는 예시입니다.
import my_library_native
result = my_library_native.my_native_function(10)
print(result)
Rust와 PyO3를 이용하여 파이썬에서 C/C++ 라이브러리를 호출하는 방법을 알아보았습니다. Rust와 PyO3를 사용하면 파이썬 프로젝트에서 안정성과 속도를 향상시킬 수 있습니다.
References:
#Rust #PyO3