从Go调用Rust函数

曾经有一篇关于Habr的文章,内容涉及如何从Go调用Rust代码这篇文章不错,但是很难理解,实际上使初学者摆脱了看两种语言的渴望。这篇文章的目的不是要深入了解跨语言调用,而是要展示它可以轻松完成。

图片

我们不会太远,并且会一本有关学习Rust语言的书为例

该示例所做的全部工作是从头10个线程开始,在该线程中它将变量'x'增加到500万,并显示有关流结束的消息。

use std::thread;

#[no_mangle]
pub extern "C" fn process() {
    let handles:Vec<_> = (0..10).map(|_|{
        thread::spawn(||{
            let mut x = 0;
            for _ in 0..5_000_000 {
                x += 1
            }
            x
        })
    }).collect();

    for h in handles {
        println!("Thread finished with count={}",
                 h.join().map_err(|_| "Could not join thread!").unwrap());
    }
    println!("Done!");
}


您还需要通过在货物文件上添加一行来编辑货物文件
板条箱类型= [“ cdylib”]
结果,将创建一个具有通过外部功能接口(FFI)调用功能的库

值得注意的是libembed.dylib是Mac OS上的一个库,在Linux上它将是libembed.so,在Windows上将是libembed.dll

谢谢:bingo347


货代
[package]
name = "embed"
version = "0.1.0"

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


通常,这是您在Rust库中要做的所有事情。书中的一个示例对此进行了更详细的描述,因此我们不再赘述。

我们使用以下命令编译库:
货物建造-放行
现在,我们的目标是从Go应用程序中调用此代码。我们创建一个简单的应用程序,并在项目内部添加lib文件夹,将/target/release/libembed.dylib文件复制到其中在内部,我们使用函数名称创建文件并描述其调用签名。

的lib / process.h
void process();


在Go文件中,我们添加了这样的指令,我们的main.go看起来像这样

package main

/*
#cgo LDFLAGS: -L./lib -lembed
#include "./lib/process.h"
*/
import "C"

func main() {
	C.process()
}


将项目放在一起
转到build -ldflags =“-r / lib” main.go
请注意ldflags参数,在这种情况下,我们要做的只是设置ELF动态链接器的路径。

所有。运行程序并获取输出。



还值得一提的是,您可以将教学内容从Go程序转移到Rust库。为此,我们在Rust库中转换函数,使其采用字符串值。

extern crate libc;
use std::thread;
use std::ffi::CStr;

#[no_mangle]
pub extern "C" fn process(name: *const libc::c_char) {

    let buf_name = unsafe { CStr::from_ptr(name).to_bytes() };
    let str_name = String::from_utf8(buf_name.to_vec()).unwrap();

    let handles:Vec<_> = (0..10).map(|_|{
        thread::spawn(||{
            let mut x = 0;
            for _ in 0..5_000_000 {
                x += 1
            }
            x
        })
    }).collect();

    for h in handles {
        println!("{}:Thread finished with count={}\n",
                 str_name,
                 h.join().map_err(|_| "Could not join thread!\n").unwrap());
    }
    println!("Done!");
}


我们组装项目,再次将库复制到lib文件夹,以这种方式修改process.h文件
无效过程(char *名称);

我们从Go应用程序传递了这一行(在本例中为“来自Golang的Hello”)

package main

/*
#cgo LDFLAGS: -L./lib -lembed
#include "./lib/process.h"
*/
import "C"

func main() {
	C.process(C.CString("Hello from Golang !!"))
}


所有。运行程序并获取输出。


All Articles