7

I have a Rust library that needs to be imported into Python via the ctypes module. My goal is to use Rust functions that take Vec<T> / i32 as arguments and return those types, from Python. Currently, I can pass integers to the Rust functions, and have them return lists / integers. Here is the current code:

Python:

import ctypes
from ctypes import cdll

class List_4(ctypes.Structure):
    _fields_ = [("array", ctypes.ARRAY(ctypes.c_int32, 4))]

rust = cdll.LoadLibrary("target/debug/py_link.dll")
rust.function_vec.restype = List_4

foobar = rust.function_i32(5)
barbaz = rust.function_vec([1, 2, 3, 4]) # Throws error: Don't know how to convert parameter

print foobar
print barbaz

Rust:

#[repr(C)]
pub struct List_4 {
    array: [i32; 4]
}

#[no_mangle]
pub extern fn function_i32(number: i32) -> i32 {
    number
}

#[no_mangle]
pub extern fn function_vec(list: List_4) -> List_4 {
    List_4 { array: [1, 2, 3, 5] }
}

What I need help with is passing a Python list as an argument to a Rust function. My best guess is to pass a ctypes.ARRAY to the function rather than a list, but I am not sure how to go about converting a Python list to that type.

Note: I tried the Rust code from this related question but it says "linking with `gcc` failed: exit code: 1" and "bad reloc address" when I try to compile it.

2
  • Is it possible to bump this question? Nobody will see it now, and I would rather have people answer this question, not a new one. Commented Jun 18, 2015 at 5:29
  • Yes, I am on Windows. Thanks for letting me know, I could do either, but it would be easier to use an array. However, it would not be too difficult to make a vector with a capacity I think, so if I can pass an array to the function, it could do a conversion. Correct me if I'm wrong. Commented Jun 19, 2015 at 1:04

1 Answer 1

4

Looks like I solved the problem. I turned the Python list into a C array, and passed that to the Rust function. Here is the working code:

#[repr(C)]
pub struct List_4 {
    // Create a struct using #[repr(C)], will do the same in Python so it is shareable
    array: [i32; 4]
}

#[no_mangle]
pub extern fn function_array(list: List_4) -> List_4 {
    // Return a new instance of List_4
    List_4 { array: [1, 2, 3, 5] }
}

Python:

import ctypes # By using ctypes, and #[repr(C)], we use the same type
              # of data in both languages, so it is possible to send stuff between them

rust = cdll.LoadLibrary("target/debug/py_link.dll") # Import the Rust dll

class List_4(ctypes.Structure):
    # Similar to creating the struct in Rust
    _fields_ = [("array", ctypes.ARRAY(ctypes.c_int32, 4))]

rust.function_array.restype = List_4 # Set the function's return type to List_4

def function_array(arr):
    # For convenience, a function to convert a list to a C array, call the function,
    # and convert its return value to a list
    return list(
        rust.function_array(
            (ctypes.c_int * len(lst))(*lst) # Call the function after converting the list 
        ).array
    )

# To use the function:
>>> function_array([1, 2, 3])
[1, 2, 3, 5]
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.