您的位置:首页 > 汽车 > 时评 > Go 调用Rust函数

Go 调用Rust函数

2024/11/13 15:37:51 来源:https://blog.csdn.net/A_super_C/article/details/141535329  浏览:    关键词:Go 调用Rust函数

Go 调用Rust函数

在golang 中,go可以引用c代码,和c共舞,也就是cgo.在一些包里就能看到cgo的身影,gopcap(引用了libpcap),go-sqlite(引用了libsqlite).毕竟c是"万物之主"嘛.本文利用cgo实现go调rust函数

这是一个rust demo用于生成动态连接库for c

lib.rs 中的demo代码

#[no_mangle]
pub extern "C" fn say_hello(name:* const i8,age:std::ffi::c_int){let rname=unsafe{let realname=std::ffi::CStr::from_ptr(name);realname.to_str().expect("to string failed")};println!("hello {rname} your age is {age}");
}

cargo toml 添加此项生成动态库和静态库 for c.也可以二选一,没必要两个都编

[lib]
crate-type=["cdylib","staticlib"]

编译好后,只要引用了这个库就可以使用say_hello函数了.
go中引用say_hello代码

package main
//#cgo LDFLAGS: -L/Users/oswaldo/dev/rs/ffi/target/release -lffi
//extern void say_hello(const char*,int);
import "C"func main(){C.say_hello(C.CString("jim"),C.int(210))
}

运行看看效果

请添加图片描述

传个结构体交流交流

Go

package main//#cgo LDFLAGS: -L/Users/oswaldo/dev/rs/ffi/target/release -lffi
//#include <stdint.h>
//struct Student{uint8_t Age;uint8_t Score;uint16_t ID;};
//extern void say_hello(const char*,int);
//extern void get_student_info(struct Student*info);
import "C"type Student struct {Age   uint8Score uint8ID    uint16
}func main() {C.say_hello(C.CString("jim"), C.int(210))var student = C.struct_Student{Age:   22,Score: 90,ID:    0x0111,}C.get_student_info(&student)
}

Rust
#[repr(C)]是灵魂,不然以rust的方式对齐,和c是错位的。这个宏告诉编译器这个结构体以c的方式对齐。go结构体内存对齐方式和c一致(这也是为什么在go中无论是调某些syscall,还是我自己写的c库,我敢放心大胆的把go中结构体指针直接传过去,只要我内存构造和c中一致就不会出问题)

#[no_mangle]
pub extern "C" fn say_hello(name: *const i8, age: std::ffi::c_int) {let rname = unsafe {let realname = std::ffi::CStr::from_ptr(name);realname.to_str().expect("to string failed")};println!("hello {rname} your age is {age}");
}
/// repr(C)是灵魂,不然以rust的方式对齐,和c是错位的。这个宏告诉编译器这个结构体以c的方式对齐。go结构体内存对齐方式和c一致
#[repr(C)]
pub struct Student {pub age: u8,pub score: u8,pub id: u16,
}
#[no_mangle]
pub extern "C" fn get_student_info(student: *mut Student) {unsafe {let stu = student.as_ref().unwrap();let level=match stu.score {0 ..= 20 =>"C",21..=70=>"B",_=>"A"};println!("id: {},score: {}, age: {}, level {level}", stu.id, stu.score, stu.age);}
}

运行看看效果

请添加图片描述

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com