C++ and Rust Compatibility

Hello,
I have a 2-D array created in C++. What is the correct of passing it to a rust shared library(it has functions to change the values in the 2-D array), basically need help with pass by reference from C++ to Rust.

Thanks.

C++ doesn't have a "2-D array" datatype. You will need to specify the exact memory layout of your type – is it vector<vector<T>> or T[M][N] or array<array<T>, M>, N>, etc.?

Hi,
Its T[M][N].

In this case, it's an array-of-arrays, which has a flat memory layout in row major format. You can access it via a *mut [[T; N]; M]. You have to ensure that T is FFI-safe, though.

A complete example where the element type is a 32-bit signed integer (for simplicity) might look like:

// C++
#include <cstdint>
#include <iostream>

using std::size_t;
using std::int32_t;

const size_t M = 2;
const size_t N = 4;

extern "C" int32_t get_last(int32_t numbers[M][N]) {
    return numbers[M - 1][N - 1];
}
// Rust
const M: usize = 2;
const N: usize = 4;

extern "C" {
    fn get_last(numbers: *const [[i32; N]; M]) -> i32;
}

fn main() {
    let array = [[1, 2, 3, 4], [5, 6, 7, 8]];
    println!("last element: {}", unsafe { get_last(&array) });
}
4 Likes

Hi, Any way to make this robust where the rust function itself does not know the size of the incoming array of arrays? Clearly here, you have defined the size, my use case is little different from this. I want to call the rust function again and again with different sized matrix. Can you please help?

Yes, that's possible, but it depends on the details. You said the type is T[M][N], but my understanding is that this type requires at least one of the lengths to be fixed.

1 Like

Can you please give an example on how to achieve this?
Let’s assume it’s not necessarily T[M][N].

let’s say I have something like this now:

int **image;
image = new int *[5];
for(int i= 0; i<5;i++)
image[i] = new int[5];

Can we pass this image to rust function in some way?

I am sorry, I am new to rust. Do not have much knowledge.

You can do almost the same if every dimension but the outermost one is known, in which case you would use *const [[i32; N]] (in Rust) and int32_t numbers[][N].

If some of the inner dimensions are unknown, then this is not something Rust supports. (It's not something standard C++ supports, either.)

1 Like

You can pass that type as an *const *const i32, or an *mut *mut i32 if it should be mutable. Accessing the array from Rust would be unsafe, but it would not be difficult to write a wrapper struct to make it easy to access an array of that form.

1 Like

Well, that's a completely different type, then. int ** is not an array-of-array type, it's a pointer-to-pointer type. In C++, arrays are not pointers and pointers are not arrays. The corresponding type in Rust would be *mut *mut c_int, which is also a pointer-to-pointer (and not an array-of-arrays) type.

1 Like

I got the point, will try this and update here if it works, thankyou guys.