python调用rust_将字符串列表从Python传递到Rust

I've been learning Rust for about two weeks now and today, I got into its FFI. I used Python to play with Rust, using ctypes and libc. I passed integers, strings and even learned to pass a list of integers (thanks to this wonderful answer).

Then, I tried to pass a list of strings (following the reasoning behind the that answer), but I failed, as I couldn't get a lead on it. In Python, I have something like this to pass the array of strings.

def testRust():

lib = ctypes.cdll.LoadLibrary(rustLib)

list_to_send = ['blah', 'blah', 'blah', 'blah']

c_array = (ctypes.c_char_p * len(list_to_send))()

lib.get_strings(c_array, len(list_to_send))

In Rust, I thought that there should be something (like a STRING_RECEIVER) to collect the incoming strings, but I can't find one.

#![feature(libc)]

extern crate libc;

use std::slice;

use libc::{size_t, STRING_RECEIVER};

#[no_mangle]

pub extern fn get_strings(array: *const STRING_RECEIVER, length: size_t) {

let values = unsafe { slice::from_raw_parts(array, length as usize) };

println!("{:?}", values);

}

Is there any alternative way to achieve this?

解决方案

There is absolutely no difference with the case of array of numbers. C strings are zero-terminated arrays of bytes, so their representation in Rust will be *const c_char, which could then be converted to &CStr which then can be used to obtain &[u8] and then &str.

Python:

import ctypes

rustLib = "libtest.dylib"

def testRust():

lib = ctypes.cdll.LoadLibrary(rustLib)

list_to_send = ['blah', 'blah', 'blah', 'blah']

c_array = (ctypes.c_char_p * len(list_to_send))(*list_to_send)

lib.get_strings(c_array, len(list_to_send))

if __name__=="__main__":

testRust()

Rust:

#![feature(libc)]

extern crate libc;

use std::slice;

use std::ffi::CStr;

use std::str;

use libc::{size_t, c_char};

#[no_mangle]

pub extern fn get_strings(array: *const *const c_char, length: size_t) {

let values = unsafe { slice::from_raw_parts(array, length as usize) };

let strs: Vec = values.iter()

.map(|&p| unsafe { CStr::from_ptr(p) }) // iterator of &CStr

.map(|cs| cs.to_bytes()) // iterator of &[u8]

.map(|bs| str::from_utf8(bs).unwrap()) // iterator of &str

.collect();

println!("{:?}", strs);

}

Running:

% rustc --crate-type=dylib test.rs

% python test.py

["blah", "blah", "blah", "blah"]

And again, you should be careful with lifetimes and ensure that Vec does not outlive the original value on the Python side.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值