简体   繁体   English

通过FFI调用Rust函数时发生访问冲突

[英]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: 一些想法:

  1. Manipulate the passed-in string to add NUL bytes at the break points, then return pointers into that large chunk. 处理传入的字符串以在断点处添加NUL字节,然后将指针返回到该大块中。 You need to be careful to not use any of the substrings after the original string has been freed. 释放原始字符串后,请务必不要使用任何子字符串。 Also the original string will now look shorter as it has embedded NUL bytes. 此外,原始字符串现在看起来较短,因为它已嵌入NUL字节。 I also don't know when Python will free the string. 我也不知道Python什么时候会释放字符串。
  2. Return an object that holds onto a 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.

相关问题 例外:从 Python 调用 C function 时读取访问冲突 - Exception: access violation reading when calling a C function from Python 调用 glutWireSphere() 时 PyOpenGL 访问冲突读取 - PyOpenGL Access Violation Reading when calling glutWireSphere() c代码中调用python函数第三次出现访问冲突写入位置错误 - an access violation writing location error the third time when calling a python function in c code Ctypes:WindowsError:异常:调用C ++函数时访问冲突读取0x0000000000000400 - Ctypes: WindowsError: exception: access violation reading 0x0000000000000400 when calling C++ function 访问.exe导出函数时,Python ctypes访问冲突 - Python ctypes access violation when accessing an .exe exported function Python调用带有ctypes的Rust FFI在退出时崩溃,“指针被释放未被分配” - Python calling Rust FFI with ctypes crashes at exit with “pointer being freed was not allocated” 通过按钮调用函数时出现 Tkinter 错误 - Tkinter error when calling function through a button OSError:使用ctypes调用DLL时出现访问冲突,读取0xXXXXXXXXXXX错误 - OSError: access violation reading 0xXXXXXXXXXXX error when calling a DLL using ctypes 使用 Rust FFI 时如何将复杂结构返回给 Python? - How do I return complex structures to Python when using Rust FFI? 使用函数参数中的字符串从Python调用Rust - Calling Rust from Python with string in the function parameters
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM