rust c++ class 사용하기

wangki·2025년 2월 1일
0

Rust

목록 보기
10/54

문제점

rust에서 cpp의 클래스를 이용하는 방법을 찾고 있다.

해결 방법

rust에서 autocxx crate를 사용하면 된다.

#pragma once
#include <vector>
#include <string>

class Test {
public:
    std::string name;
    uint32_t horns;

    // Test(const std::string& name, uint32_t horns) : name(name), horns(horns) {}

    std::string get_name() {
        return name;
    }

    void set_name(const std::string& name) {
        this->name = name;
    }
};

Test Class가 있다고 하자. rust에서 Test의 객체를 만들어서 사용하는 법을 알아보겠다.

[dependencies]
autocxx = "0.27.1"
cxx = "1.0.78"


[build-dependencies]
autocxx-build = "0.27.1"

cargo.toml 파일에 위와같이 의존성과 빌드 의존성을 추가해준다.

autocxx::include_cpp! {
    #include "test_wrapper.h"
    safety!(unsafe_ffi)
    generate!("TestWrapper")
    generate!("Test")
}

include_cpp! 매크로를 사용한다. #include로 불러올 헤더파일을 인클루드 해준다.

기본적으로 include_cpp를 통해 생성된 c++ 코드는 unsafe하다 즉, unsafe코드 블록안에서 사용해야한다.
safety! 매크로를 include_cpp!매크로 내부에 명시적으로 사용할 경우 compiler에게 c++코드가 안전하지 않다고 말해주는 것 과 같다.

generate는 c++ 코드를 rust에서 호출할 수 있도록 바인딩된 코드를 생성해준다.
1. c++ 헤더 파일을 분석하여 클래스, 함수, 변수 등의 정보를 추출한다.
2. 추출된 정보를 바탕으로 rust에서 c++ 코드를 호출하기 위해 바인딩된 코드를 생성한다.
3. c++타입과 rust타입 간의 변환 코드를 생성한다.

Test 클래스를 객체화하여 사용하기 위한 코드를 살펴보겠다.

  let mut test = ffi::Test::new().within_unique_ptr();
  let_cxx_string!(name = "dog");
  test.pin_mut().set_name(&name);
  let test_name = test.pin_mut().get_name();
  println!("test name : {}", test_name);

Test::new()를 통해서 객체를 만들어준다. c++코드에서 Test class에 생성자를 지정하지 않으면 기본적으로 new 함수를 생성해주는 것 같다. let_cxx_string! 매크로를 통해서 CxxString 타입의 문자열을 만들어준다. Test 객체의 메서드들을 통해서 내부 필드 값을 초기화 후 읽는 코드이다.

마지막으로 build.rs

fn main() -> miette::Result<()> {
    let include_path = std::path::PathBuf::from("src");

    // This assumes all your C++ bindings are in main.rs
    let mut b = autocxx_build::Builder::new("src/main.rs", &[&include_path]).build()?;
    b.flag_if_supported("-std=c++14")
     .compile("autocxx-demo"); // arbitrary library name, pick anything
    println!("cargo:rerun-if-changed=src/main.rs");

    // Add instructions to link to any C++ libraries you need.

    Ok(())
}

header파일이 있는 경로와 c++ 객체를 사용할 경로를 지정해준다.

결론

c++과 rust는 기본적으로 ffi가 완벽히 호환되지 않는다.
autocxx, cxx 등 ffi 크레이트를 활용하여 c++의 코드를 rust에서, rust의 코드를 c++에서 사용할 수 있다.
좀더 깊은 내용은 https://google.github.io/autocxx/index.html에서 공부해야겠다.

0개의 댓글