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   uint8
	Score uint8
	ID    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);
    }
}

运行看看效果

请添加图片描述

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值