Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/rust/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
制作C+时是否应使用Pin+;通过指针调用Rust方法? < >我有C++代码,用数据调用锈蚀代码。它知道将数据发送到哪个对象。下面是C++调用的生锈函数的例子: extern“C”fn打开vpn接收( 实例:Box, 数据:*mut c_uchar, 尺寸:*多个尺寸, )->u8_Rust_Ffi_Rust Pin - Fatal编程技术网

制作C+时是否应使用Pin+;通过指针调用Rust方法? < >我有C++代码,用数据调用锈蚀代码。它知道将数据发送到哪个对象。下面是C++调用的生锈函数的例子: extern“C”fn打开vpn接收( 实例:Box, 数据:*mut c_uchar, 尺寸:*多个尺寸, )->u8

制作C+时是否应使用Pin+;通过指针调用Rust方法? < >我有C++代码,用数据调用锈蚀代码。它知道将数据发送到哪个对象。下面是C++调用的生锈函数的例子: extern“C”fn打开vpn接收( 实例:Box, 数据:*mut c_uchar, 尺寸:*多个尺寸, )->u8,rust,ffi,rust-pin,Rust,Ffi,Rust Pin,它接收指针为 box ,因此我创建了一个函数:代码> OpenVpnStIsRuStSuthOuts,它设置C++必须调用的对象。此对象是指向自身的指针。我使用的是 PIN ,所以框没有重新分配到其他地方,使C++调用无效地址。 impl OpenVpn{ pub fn new()->Pin{ let instance=unsafe{interface::openvpn_new(profile.as_ptr())}; 设o=OpenVpn{instance:instance}; 设p=Box::

它接收指针为<代码> box <代码>,因此我创建了一个函数:代码> OpenVpnStIsRuStSuthOuts<代码>,它设置C++必须调用的对象。此对象是指向自身的指针。我使用的是<代码> PIN <代码>,所以<代码>框没有重新分配到其他地方,使C++调用无效地址。
impl OpenVpn{
pub fn new()->Pin{
let instance=unsafe{interface::openvpn_new(profile.as_ptr())};
设o=OpenVpn{instance:instance};
设p=Box::pin(o);
不安全{
接口::openvpn_set_rust_parent(o.instance,p.as_ptr());
};
P
}
}
签名:

pub fn openvpn\u set\u rust\u parent(实例:*mut openvpn实例,父实例:*mut openvpn)
<>我不知道如何将>P<代码>转换成<代码> *MUT OpenVPN < /C> >传递给C++。我的主意行吗?我认为使用<代码> PIN <代码>是很好的,我认为这是一个从C++调用对象的好方法。

没关系。code>Pin并不是一种让你的价值永远不动的神奇类型。事实上,它可以归结为措辞强硬的文档和一些防止您在安全代码中做坏事的指南<代码>Pin可以通过不安全代码(包括任何FFI代码)规避

Pin
放在锈迹代码中可能有助于保持锈迹代码的准确性和有效性,但对于从其他语言调用锈迹代码来说,它没有任何用处

作为
repr(透明)
,这意味着您可以在您的FFI签名中使用它,只要在FFI中使用内部类型是安全的:

#[稳定(feature=“pin”,自=“1.33.0”)]
#[lang=“pin”]
#[基础]
#[报告(透明)]
#[衍生(复制、克隆)]
发布结构Pin

{ 指针:P, }

我使用<代码> PIN < /C> >因此<>代码> box <代码>不重新分配到其他地方,使C++调用无效地址。< /P>
Pin
不执行此操作,
Box
执行此操作。当您装箱时,您将值移动到堆中。
框本身就是一个指针。指针的地址将四处移动,但堆中数据的地址不会移动

请注意,打印的第二个地址(堆上的
0x55..30
)是相同的,即使
框本身已移动:

fn main(){
设a=42;
设b=Box::new(a);
println!({:p},&b);//0x7ffe3598ea80
println!({:p},&*b);//0x556d21528b30
设c=b;
println!({:p},&c);//0x7ffe3598ea88
println!({:p},&*c);//0x556d21528b30
}
另见:


“重要。至少在目前,对于C中定义但从Rust调用的函数,应该避免使用Box类型。”-来自。因此,首先不要写这个签名。@SebastianRedl虽然这是真的(而且很有趣,感谢链接),但这是一个非常迂腐的问题,这个问题似乎是问一个在Rust中定义的从C(++)调用的函数。看来同样的逻辑也适用于相反的方向。@trentcl啊,没错。我误解了这篇文章的那一部分。不,逻辑并没有相反的方向。它以
框的形式接收指针-这是非常可疑的,因为这意味着函数必须被调用一次。如果称为零次,则表示内存泄漏。如果它被调用两次,那么在释放后,您将使用内存。考虑到您从函数返回
p
,这意味着一旦触发回调,任何访问
p
的锈迹代码都将导致未定义的行为。同上,如果代码出现在回调之前,代码会被锈迹代码删除。@代码生成C++代码,并被代码> OpenVPN < /C> >破坏,所以C代码就像是代码< OpenVPN > /代码>所拥有的。<代码> OpenVPNSSETHUSTSTYRADION/CODEC>只在C++类中设置回调,以便知道要调用哪个对象(其父)。调用两次或多次只会再次设置回调。而且它也不可能什么都不叫,因为它叫它的父母,而父母总是比它活得更久。因此,考虑到这些事实,我认为调用
openvpn\u set\u rust\u parent
并仍然返回
p
是有意义的。你怎么想?我一直有点不清楚
#[稳定]
项目的哪些方面已经稳定下来;我由此推测,
repr
保证稳定?那么既然
Box
在FFI中使用是安全的,这是否意味着Pin是安全的?我应该只调用
不安全的{interface::openvpn_set_rust_parent(o.instance,p);};p
?Ps:我不能这样做,因为我要把p移到
openvpn\u set\u rust\u parent
@eggyal,我不知道稳定性和
repr
之类的东西是否已经明确地写在任何地方,但和许多事情一样,它通常是单行道。我现在忘记了确切的类型,但是有一个stdlib类型没有
repr
属性(因此是
repr(Rust)
),它确实变为
repr(透明)
。这很好,因为它从“未定义的布局”变为“已定义的布局”,但这不能在不破坏东西的情况下更改回去。我很乐意假设
Pin
将永远是
repr(透明)
,除非发现了一些内存不安全的错误。@GuerlandoOCs,如您问题的评论中所述,虽然
Box
可以放入FFI签名,但这并不意味着它的每一次使用都是正确的。例如,你不可能所有的