如何从其他语言访问Rust 以前,当代码库是C++时,我有C++的包装文件,这些文件将链接到代码库,我将运行 SWIG/(C++ 3支持的版本11),生成目标语言的接口文件(Python、JavaScript、C等)。然后,将所有这些文件和库编译成一个共享对象,并从所需的语言调用它。现在,代码库被改为rust。因此,对于swig的工作,我有以下几点: 编译成rlib的主rust代码文件 Rust包装文件,它调用主代码库,但对FFI使用no\u mangle和extern语法,并编译成staticlib 调用锈迹包装器的C文件,它是锈迹包装器的副本
现在我在C文件上使用如何从其他语言访问Rust 以前,当代码库是C++时,我有C++的包装文件,这些文件将链接到代码库,我将运行 SWIG/(C++ 3支持的版本11),生成目标语言的接口文件(Python、JavaScript、C等)。然后,将所有这些文件和库编译成一个共享对象,并从所需的语言调用它。现在,代码库被改为rust。因此,对于swig的工作,我有以下几点: 编译成rlib的主rust代码文件 Rust包装文件,它调用主代码库,但对FFI使用no\u mangle和extern语法,并编译成staticlib 调用锈迹包装器的C文件,它是锈迹包装器的副本,rust,swig,Rust,Swig,现在我在C文件上使用swig,获取目标语言的接口文件,将所有文件(步骤2和步骤3)和swig接口文件)合并到一个共享对象中,并从目标语言调用 因此: 这种方法行吗 我可以使用免费函数。然而,我对如何让成员函数(方法)工作感到困惑。在C++中,成员函数的第一个参数是隐式这个< /C>指针。因此,我可以将类或结构的void*句柄返回给C接口,该接口将把它传递给希望存储它的其他人(例如,Firefox的jsctypes),然后在再次接收reinterpret\u cast时将其转换为具体/实际类型并调
swig
,获取目标语言的接口文件,将所有文件(步骤2和步骤3)和swig接口文件)合并到一个共享对象中,并从目标语言调用
因此:
void*
句柄返回给C接口,该接口将把它传递给希望存储它的其他人(例如,Firefox的jsctypes),然后在再次接收reinterpret\u cast
时将其转换为具体/实际类型并调用其上的成员函数。我如何处理锈迹pub结构A{id:SomeType,}
暗示{
pub fn某些函数0(&mut self){
pub fn某些函数1(&self){
}
将某个特征应用于{
fn某些特征函数(&mut self){
}
那么,我如何从目标语言(Python、C等)甚至仅仅是一个C接口访问
A
对象(我想应该是非托管的,在堆上?)上的这些成员函数呢?好吧,方法只是常规函数,正如Chris所说,self
参数与self
类型有隐式的联系。对于您的示例(稍加修改),使用C代码中的函数应该很简单:
#[repr(C)]
发布结构A{id:u32,}
#[没有损坏]
酒吧外间新店a(id:u32)->a{
A{id:id}
}
暗示{
#[没有损坏]
pub extern fn某些函数(&self){
println!(“称为某些函数:{},self.id);
}
}
特质{
外部的某些特征功能(自身);
}
将某个特征应用于{
#[没有损坏]
外部fn某些特性函数(&self){
println!(“称为某些特征函数:{},self.id);
}
}
请注意,我添加了extern
以更改调用约定,并在结构上添加了#[no_mangle]
以避免名称损坏和#[repr(C)]
。如果代码创建结构的Box
es并将它们作为原始指针传递给C,则不需要后者。但是,我不确定如果有多个trait实现者,[no#mangle]
会如何影响trait方法-如果两个trait实现者都有[no#mangle]
,那么肯定会有某种名称冲突
现在使用C中的此类型及其函数很容易:
#包括
结构A{
uint32_t id;
};
一个新的外部结构(uint32\t id);
外部无效某些函数(const struct A*self);
外部无效某些特征函数(const struct A*self);
int main(){
结构A=新的(123);
一些函数(&a);
某些特征函数&a;
}
该程序编译并运行:
% rustc --crate-type=staticlib test.rs
multirust: a new version of 'nightly' is available. run `multirust update nightly` to install it
note: link against the following native artifacts when linking against this static library
note: the order and any duplication can be significant on some platforms, and so may need to be preserved
note: library: System
note: library: pthread
note: library: c
note: library: m
% gcc -o test_use test_use.c libtest.a -lSystem -lpthread -lc -lm
% ./test_use
Called some_funct: 123
Called some_trait_funct: 123
如果接受方法&mut self
:
#[无损坏]
外部fn某些函数mut(&mut self){…}
您需要省略const
:
extern void一些函数(结构A*self);
如果接受方法self
:
#[无损坏]
某些函数值(自){…}
您需要按值传递结构:
extern void一些函数值(结构自身);
尽管如果通过不透明指针使用该结构,调用按值获取该结构的函数可能会很困难,因为C必须知道该结构的确切大小。我相信不透明指针并不常见。好吧,我在接受的答案中评论说我不能使用这种方法,我最后做了类似的事情,让其他人评论: 编译到
rlib
的后端代码:
pub trait TestTrait {
fn trait_func(&mut self) -> i32;
}
pub struct TestStruct {
value: i32,
}
impl TestStruct {
pub fn new(value: i32) -> TestStruct {
TestStruct {
value: value,
}
}
pub fn decrement(&mut self, delta: i32) {
self.value -= delta;
}
}
impl TestTrait for TestStruct {
fn trait_func(&mut self) -> i32 {
self.value += 3;
self.value
}
}
上面的锈迹包装器链接到上面的rlib
,并编译成staticlib
(例如,Linux中的.a
):
现在只需在目标语言的C文件上运行SWIG
(我刚刚发布了.C
文件-您可以猜测SWIG将在其上运行的.h
),获得它生成的接口_wrap.C
,并编译这些源代码链接,根据staticlib
获取共享对象
例如,对于python:
swig -python interface.i
gcc -std=c99 -c -fPIC -Wall -Werror -O2 api.c interface_wrap.c -I/usr/include/python2.7
gcc -shared -o _port_sample.so api.o interface_wrap.o -L./ -lrust_wrapper
现在只需从Python调用,整个过程就可以正常工作:
$ python
Python 2.7.6 (default, Mar 22 2014, 22:59:56)
[GCC 4.8.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import port_sample
>>> handle = port_sample.new_test_struct(36)
>>> port_sample.test_struct_decrement(handle, 12)
>>> value = port_sample.test_struct_trait_function(handle)
>>> print value
27
>>> exit()
我希望有人觉得这很有用,并且/或者可以提出改进建议等。我也已经让这件事起作用并致力于我的github报告:在方法定义中,
self
是self:self
的糖分,&self
是self:和&mut-self
的糖分。当然,self
关键字在Rust中仍然很特别,但是A::some_trait_functt
和A::some_functt_0
仍然是以&mut A
作为第一个参数类型的函数。您可以尝试通过编译器插件创建自己的属性,该插件会自动插入no_mangle
,为该函数创建一个c头文件并在其上运行swig。注意:当您返回struct by value时,返回值最终为void,实际返回值必须写入函数的第一个参数(addit
swig -python interface.i
gcc -std=c99 -c -fPIC -Wall -Werror -O2 api.c interface_wrap.c -I/usr/include/python2.7
gcc -shared -o _port_sample.so api.o interface_wrap.o -L./ -lrust_wrapper
$ python
Python 2.7.6 (default, Mar 22 2014, 22:59:56)
[GCC 4.8.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import port_sample
>>> handle = port_sample.new_test_struct(36)
>>> port_sample.test_struct_decrement(handle, 12)
>>> value = port_sample.test_struct_trait_function(handle)
>>> print value
27
>>> exit()