[英]Access violation when calling Rust function through FFI
As the title states, I get an access violation when I try to call the following Rust code in Python. 如标题所示,当我尝试在Python中调用以下Rust代码时,出现访问冲突。
Here's the Rust code: 这是Rust代码:
#![crate_type = "dylib"]
extern crate libc;
use libc::c_char;
use std::ffi::CStr;
use std::str;
#[repr(C)]
pub struct AdditionalDetail {
swis: String,
sbl: String,
school_code: String,
land_assessed_value: u32,
deed_book: String,
deed_page: String,
}
#[no_mangle]
pub extern fn parse_details(l: *const c_char) -> AdditionalDetail{
let _line = unsafe {
assert!(!l.is_null());
CStr::from_ptr(l)
};
let line = str::from_utf8(_line.to_bytes()).unwrap();
let _swis = line[52..58].to_owned();
let _sbl = line[58..78].to_owned();
let _school_code = line[371..377].to_owned();
let _land_assessed_value = line[824..836].parse::<u32>().ok().expect("Couldn't convert to an int");
let _deed_book = line[814..819].to_owned();
let _deed_page = line[819..824].to_owned();
AdditionalDetail{swis: _swis, sbl: _sbl, school_code: _school_code, deed_page: _deed_page,
land_assessed_value: _land_assessed_value, deed_book: _deed_book}
}
And the Python code I'm using to call it: 还有我用来调用它的Python代码:
from ctypes import cdll, c_uint32, Structure, c_char_p
class TaxDetail(Structure):
_fields_ = [('swis', c_char_p),
('sbl', c_char_p),
('school_code', c_char_p),
('land_assessed_value', c_uint32),
('deed_book', c_char_p),
('deed_page', c_char_p), ]
def __str__(self):
return str(self.swis)
lib = cdll.LoadLibrary(r"C:\Rust Workspace\embed\target\release\embed.dll")
lib.parse_details.restype = TaxDetail
lib.parse_details.argtype = (c_char_p,)
result = lib.parse_details(b"1346011 63 WAP WEST LLC 00000101 13460100615800142703690000 63 Wap West LLC 10 Fair Oaks Dr Poughkeepsie, NY 12603 000500000150000000017135601 14270369 411 000001 1 4-6Church St 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006158-14-270369-0000 058369006127002200002074000000052500000000286000N 0000000028600000000000000000000000000000000000Y")
print(result)
I've added println!
我添加了
println!
calls to my Rust code, and the access violation seems to occur when it tries to create and return the struct. 调用我的Rust代码,并且在尝试创建并返回struct时似乎发生访问冲突。 The specific error message I'm getting is
Process finished with exit code -1073741819 (0xC0000005)
. 我收到的特定错误消息是
Process finished with exit code -1073741819 (0xC0000005)
。
This happens with 32 bit Rust and Python on 64 bit Windows 10. 在64位Windows 10上使用32位Rust和Python会发生这种情况。
I'm not sure of the full extent of the issues, but I know this one isn't going to be good: you can not return a String
through FFI. 我不确定问题的全部范围,但是我知道这不会很好:您无法通过FFI返回
String
。
A Rust String
is conceptually 3 parts: a pointer to a chunk of memory, how long that memory is, and how much of that memory is a valid string. 从概念上讲,Rust
String
由3部分组成:指向大块内存的指针,该内存有多长时间以及该内存中有多少是有效字符串。
Compare that to a C string. 将其与C字符串进行比较。 AC string is just a pointer to memory.
AC字符串只是指向内存的指针。 You don't know how much memory there is, and you only know the valid length by walking down every single byte until you get to a NUL byte.
您不知道有多少内存,只能通过向下浏览每个字节直到获得NUL字节来知道有效长度。
Even more than that, a String
isn't marked as #[repr(C)]
, so the actual layout of the String
structure is up to the Rust compiler. 甚至不止如此,
String
还没有标记为#[repr(C)]
,因此String
结构的实际布局取决于Rust编译器。
I suspect that the error occurs because Python sees you are returning a c_char_p
(which I assume is a char *
). 我怀疑发生错误是因为Python看到您正在返回
c_char_p
(我假设是char *
)。 It then tries to read a pointer's worth of data and then moves to the next pointer. 然后,它尝试读取指针的数据,然后移动到下一个指针。 The "pointer" it reads may be the
String
's pointer or length or capacity, and as soon as it reads the second one it's off in the weeds somewhere. 它读取的“指针”可能是
String
的指针,长度或容量,一旦读取了第二个指针,它就会在杂草中消失。
Instead, you will need to figure out alternative ways of dealing with this string. 相反,您将需要找出处理此字符串的替代方法。 A few thoughts:
一些想法:
CString
and has methods that return the result of as_ptr
. CString
并具有返回as_ptr
结果的方法的as_ptr
。 A similar logic applies for &str
, which is conceptually a pointer to a chunk of memory and how much of that memory is valid. 类似的逻辑适用于
&str
,从概念上讲是指向内存块以及该内存有多少有效的指针。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.