- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我有一个用 Rust 编写的 C FFI,名为 src/lib.rs
,如下所示:
// compile with $ cargo build
extern crate libc;
use self::libc::{size_t, int32_t};
use std::cmp::min;
use std::slice;
#[no_mangle]
pub extern "C" fn rle_new(values_data: *const int32_t, values_length: size_t) -> *mut Rle {
let values = unsafe { slice::from_raw_parts(values_data, values_length as usize).to_vec() };
return Box::into_raw(Box::new(Rle::new(values)));
}
#[no_mangle]
pub extern "C" fn rle_free(ptr: *mut Rle) {
if ptr.is_null() {
return;
}
unsafe {
Box::from_raw(ptr);
}
}
#[no_mangle]
pub extern "C" fn rle_values_size(rle: *mut Rle) -> int32_t {
unsafe { (*rle).values.len() as i32 }
}
#[no_mangle]
pub extern "C" fn rle_values(rle: *mut Rle) -> *mut int32_t {
unsafe { &mut (*rle).values[0] }
}
#[derive(Debug, PartialEq)]
pub struct Rle {
pub values: Vec<i32>,
}
impl Rle {
pub fn new(values: Vec<i32>) -> Self {
return Rle { values: values };
}
}
这是项目基础文件夹中我的 Cargo.toml:
[package]
name = "minimal_example"
version = "0.1.0"
authors = ["Dumbass"]
[dependencies]
libc = "0.2.16"
[lib]
crate-type = ["dylib"] # you might need a different type on linux/windows ?
这是调用 Rust 的 Python 代码,也放在 base 文件夹中:
import os
import sys, ctypes
from ctypes import c_char_p, c_uint32, Structure, POINTER, c_int32, c_size_t, pointer
class RleS(Structure):
pass
prefix = {'win32': ''}.get(sys.platform, 'lib')
extension = {'darwin': '.dylib', 'win32': '.dll'}.get(sys.platform, '.so')
libpath = os.environ.get("LD_LIBRARY_PATH", "target/debug") + "/"
libpath = libpath + prefix + "minimal_example" + extension
try:
lib = ctypes.cdll.LoadLibrary(libpath)
except OSError:
print("Library not found at " + libpath)
sys.exit()
lib.rle_new.restype = POINTER(RleS)
lib.rle_free.argtypes = (POINTER(RleS), )
lib.rle_values.argtypes = (POINTER(RleS), )
lib.rle_values.restypes = POINTER(c_int32)
lib.rle_values_size.argtypes = (POINTER(RleS), )
lib.rle_values_size.restypes = c_int32
class Rle:
def __init__(self, values):
values_length = len(values)
values_array = (c_int32 * len(values))(*values)
self.obj = lib.rle_new(values_array, c_size_t(values_length))
def __enter__(self):
return self
def __exit__(self, exc_type, exc_value, traceback):
lib.rle_free(self.obj)
def __str__(self):
values_size = lib.rle_values_size(self.obj)
print(values_size, "values_size") # prints correct value
values_pointer = lib.rle_values(self.obj)
print("values_pointer:", values_pointer)
ar = ctypes.cast(values_pointer, ctypes.POINTER(ctypes.c_int32)).contents
print(ar) # segfaults!
rle = Rle([1, 1, 2] * 10)
print(rle)
我有充分的理由相信 C 代码是正确的,因为 rle_values_size
和 rle_values
指的是同一个对象,即结构中的 Rust 向量,并且rle_values_size
函数有效。
但是,当我尝试取消引用 rle_values
给出的指针并将其作为数组读取时,我遇到了段错误。
我已经尝试了在 Stack Overflow 上找到的代码片段的每一个排列,但它会出现段错误。
为什么会崩溃?我做错了什么?
我添加了 Rust 标签,因为我可能以错误的方式获取向量的地址。
附言。如果有人也知道如何将其直接读入 numpy 数组,我也会赞成。
最佳答案
cast
应该是第一个警告标志。为什么必须从类型转换为应该相同的类型?这是因为有简单的错别字:
lib.rle_values.restype = POINTER(c_int32)
lib.rle_values_size.restype = c_int32
请注意,它应该是restype
,而不是restypes
。
def __str__(self):
values_size = lib.rle_values_size(self.obj)
print(values_size, "values_size")
values_pointer = lib.rle_values(self.obj)
print("values_pointer:", values_pointer)
thing = values_pointer[:values_size]
return str(thing)
使用as_mut_ptr
也更好:
#[no_mangle]
pub extern "C" fn rle_values(rle: *mut Rle) -> *mut int32_t {
let mut rle = unsafe { &mut *rle };
rle.values.as_mut_ptr()
}
运行程序似乎有效:
$ LD_LIBRARY_PATH=$PWD/target/debug/ python3 main.py
new
30 values_size
values_pointer: <__main__.LP_c_int object at 0x10f124048>
[1, 1, 2, 1, 1, 2, 1, 1, 2, 1, 1, 2, 1, 1, 2, 1, 1, 2, 1, 1, 2, 1, 1, 2, 1, 1, 2, 1, 1, 2]
我还建议:
cint
。不为 free
指定返回类型可能不是一个好主意,因为它应该是 void
。unsafe
block 的范围缩小到仅不安全的部分和确保它实际上安全的代码。说到这里,您可以检查每个函数中的 NULL
指针。
#[no_mangle]
pub extern "C" fn rle_values_size(rle: *mut Rle) -> int32_t {
match unsafe { rle.as_ref() } {
Some(rle) => rle.values.len() as i32,
None => 0,
}
}
#[no_mangle]
pub extern "C" fn rle_values(rle: *mut Rle) -> *mut int32_t {
match unsafe { rle.as_mut() } {
Some(mut rle) => rle.values.as_mut_ptr(),
None => ptr::null_mut(),
}
}
关于python - 在 Python 中取消引用 FFI 指针以获取底层数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40219711/
我正在努力通过接受 void 的 FFI 传递结构并在另一端读回它。 有问题的库是 libtsm,一个终端状态机。它允许您提供输入,然后找出输入后终端将处于哪种状态。 它将其绘制函数声明为: pub
只是为了测试目的,我在 delphi 中创建了一个小的 DLL。代码为: library MyDll; uses SysUtils, Classes, Vcl.Dialogs;
这是我一直好奇的事情:我想知道 LuaJIT 的 FFI 模块如何设法使用正确的调用约定来调用外部 native 函数,而无需在用户原型(prototype)中进行任何声明。 我尝试阅读源代码以自己解
我有一个带有函数的 C 库,在一个不透明的结构上运行,定义如下: Foo* makeFoo(); // create a new Foo Foo* dupFoo(const Foo* orig); /
我正在尝试从 purescript 调用 navigator.geolocation.getCurrentPosition javascript 函数,但遇到了两个问题。 在 javascript 中
ruby 版本 2.2.4p230 RubyGem 版本 2.7.2 已安装 Ruby-devel 和 lib64ffi-devel。 使用 64 位 OpenMandriva 3.0、urpmi 和
我正在尝试使用 FFI 将以下 JavaScript 函数导入 PureScript: function getGreeting() { return "Hi, welcome to the sh
我对 Haskell 中的 FFI 有一些疑问 我知道我必须使用语言编译指示 {-# LANGUAGE ForeignFunctionInterface #-}但是当我使用 {-# LANGUAGE
当我尝试构建 Flutter项目至 IOS 它向我显示了这个错误,我尝试清理并尝试更改项目的目录。 Launching lib/main.dart on iPhone 12 Pro Max in de
完整堆栈跟踪: /Users/galharth/.rvm/gems/ruby-2.3.0/gems/activesupport-4.2.5/lib/active_support/dependencie
我试过运行 pod install在我的 Xcode 项目中,但出现以下错误 /System/Library/Frameworks/Ruby.framework/Versions/2.6/us
我需要在节点 Electron 项目中使用模块“ffi”。我可以使用“gyp”重建它并在节点中使用库,但我不能使用“electron-rebuild”重建它并在 Electron 中使用它。 我跑了:
以下警告是什么意思,我该如何解决它的原因? Warning: Unimplemented primitive used:removeEventListener 在 [@bs.val] external
谁能告诉我一个使用带有可变参数的 C 函数(例如 printf )和 Haskell 的外部函数接口(interface)的示例?我尝试搜索 HaskellWiki,但没有找到这样的示例。 谢谢! 最
我使用 FFI 是为了在 C 中使用一个函数,该函数接受一个结构并返回相同的结构。我看到的引用说我必须使用指向这些结构的指针才能将其导入 Haskell。所以,例如。 data Bar = Bar {
我想在带有 FFI 的 Rust 中包含一个动态 C 库。 该库实际上也是用 Rust 构建的,但公开了一个 C 接口(interface),因此它也可以从其他语言中使用。当我用 cargo 构建库(
我试图在winapi上写一个包装器。我想包装接受回调函数指针的函数。 例如,考虑以下情况: // The unsafe callback type the FFI function accepts t
我正在使用 rust-bindgen 从 Rust 访问 C 库。一些函数返回指向结构的可空指针,bindgen 表示为 extern "C" { pub fn get_some_data()
介绍 我正在用 inline-c 包装一个 C 数值库;一些函数可以将回调传递给步骤例程,考虑 ODE 的优化或时间积分。 特别是在原生 C 中,使用回调可以对连续数组进行操作,通过指针修改它们,并将
fn main() { let val = 0; unsafe { foo(&val) } } extern "C" { pub fn foo(val: *const u32)
我是一名优秀的程序员,十分优秀!