Search code examples
c++rustffi

rust autocxx not getting the right values from c++


I am trying to run some rust code in c++ as practice but I don't know why I am getting weird values here:

cmake_minimum_required(VERSION 3.11.0)
project(4Gewinnt VERSION 0.2.1)

include(CTest)
enable_testing()

add_library(ai_lib SHARED
    src/mirror_ai.cpp
)

# Add the Rust project as an external dependency
include(ExternalProject)

ExternalProject_Add(
    rust_example
    SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/rust_example"
    BINARY_DIR "${CMAKE_CURRENT_SOURCE_DIR}/rust_example"
    CONFIGURE_COMMAND ""
    BUILD_COMMAND cargo build --release
    INSTALL_COMMAND ""
    BUILD_BYPRODUCTS "${CMAKE_CURRENT_SOURCE_DIR}/rust_example/target/release/librust_example.so" # Adjust the library name if needed
)

# Specify the C++ executable target
add_executable(VierGewinnt
    src/main.cpp
    src/base_entity.cpp
    src/board.cpp
    src/color.cpp
    src/difficulty.cpp
    src/easy_ai.cpp
    src/game.cpp
    src/hard_ai.cpp
    src/medium_ai.cpp
    src/player.cpp
)

target_link_libraries(VierGewinnt PRIVATE ai_lib)

# Add a custom command to build the Rust project
add_custom_command(TARGET VierGewinnt POST_BUILD
    COMMAND cargo build --release
    WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/rust_example"
    COMMENT "Building Rust project"
)

# Link against the Rust library
add_dependencies(VierGewinnt rust_example)
target_link_libraries(VierGewinnt PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/rust_example/target/release/librust_example.so") # Adjust the library name if needed

# Include directories
target_include_directories(VierGewinnt PRIVATE
    include
    lib
    "${CMAKE_CURRENT_SOURCE_DIR}/rust_example/include"
)

target_compile_features(VierGewinnt PUBLIC cxx_std_20)
target_compile_options(VierGewinnt PUBLIC -Wall -pedantic -Wextra)

rust.hpp

#pragma once
#include "board.hpp"

extern "C" {
Column rust_main(Board board, int length);
}

medium_ai.cpp

#include "medium_ai.hpp"
#include "rust.hpp"
#include <iostream>

Column MediumAI::choose_slot(const Board &board) {
  int length = board.columns();
  std::cout << "[cpp] board.columns: " << length << std::endl;
  Column result = rust_main(board, length);

  return result;
}

lib.rs

use autocxx::prelude::*;
use rand::Rng;

include_cpp! {
    #include "board.hpp"
    #include "column.hpp"
    safety!(unsafe_ffi)
    generate!("Board")
    generate!("Column")
}

#[no_mangle]
pub extern "C" fn rust_main(board: ffi::Board, length: i32) -> UniquePtr<ffi::Column> {
    println!(
        "[rust] board.columns: {}, length: {}",
        board.columns(),
        length
    ); // --> both random and different

    let mut rand_slot: usize;
    let mut rng = rand::thread_rng();

    loop {
        rand_slot = rng.gen_range(0..=board.columns());
        println!("[rust] rand_slot: {}", rand_slot);

        if !board.is_full(ffi::Column::new(rand_slot).within_unique_ptr()) {
            break;
        }
    }

    let column = ffi::Column::new(rand_slot).within_unique_ptr();
    column
}

in the medium_ai the cout says its 7 like it should be in the rust file they are like c++ when you print a c++ value when they are initialized but don't have a value.

can somebody tell me what I am doing wrong?


Solution

  • Make board a reference in the signature of rust_main in lib.rs, i.e. change

    pub extern "C" fn rust_main(board: ffi::Board, length: i32) -> UniquePtr<ffi::Column>
    

    to

    pub extern "C" fn rust_main(board: &ffi::Board, length: i32) -> UniquePtr<ffi::Column>