简体   繁体   English

如何使用切片作为参数从Go调用Rust函数?

[英]How can I call a Rust function from Go with a slice as a parameter?

I want to call some external functions written in Rust from Go with a reference to a slice. 我想调用一些用Rust编写的外部函数来引用一个切片。

I have the following Rust code: 我有以下Rust代码:

extern crate libc;

#[no_mangle]
pub extern "C" fn callme(data: &mut [libc::c_double]) -> i32 {
    data.len() as i32
}

This function is made available for the cgo compiler through this C-style header file: 此函数通过此C风格的头文件可用于cgo编译器:

#IFNDEF BOGUSLIB_H
#DEFINE BOGUSLIB_H

extern int callme(double* data);    

#ENDIF

I can now call this function from Go with the Rust crate compiled as a cdylib: 我现在可以使用编译为cdylib的Rust crate从Go调用此函数:

//#cgo CFLAGS: -Ipath/to/libfolder
//#cgo LDFLAGS: -Lpath/to/libfolder -lboguslib
//#include <boguslib.h>
import "C"
import (
   "unsafe"
   . "fmt"  
)

func CallmeExternal() {
   data := make([]float64, 1, 1)
   data[0] = 1.0
   ptr := (*C.double)(unsafe.Pointer(&data[0]))
   size := C.callme(ptr)

   printf("size %v",size)
}

The Go code uses the unsafe pointer trick to access the backing array, since a slice is defined as follows Go代码使用不安全指针技巧来访问支持数组,因为切片定义如下

type Slice struct {
   data *byte
   uint32 len
   uint32 cap
}

When I execute the code above, the length of the passed reference is incredibly large. 当我执行上面的代码时,传递的引用的长度非常大。 How do I access the actual data, and what is at this moment being returned? 如何访问实际数据,以及此时返回的内容是什么?

According to The Rust FFI Omnibus as provided by @matthieu-m , I have successfully rewritten the code. 根据@ matthieu-m提供的 The Rust FFI Omnibus ,我已经成功地重写了代码。 The function signature must accept the types understood by the target language. 函数签名必须接受目标语言理解的类型。

The Rust function signature changed to: Rust函数签名更改为:

#[no_mangle]
pub extern "C" fn callme(slice: *const libc::c_double, len: libc::size_t) -> libc::c_int {
    let data = slice::from_raw_parts(slice, len as usize);
    data.len() as i32
}

The declaration in the header file as follows: 头文件中的声明如下:

// skip include guards
#include <stdio.h>

extern int callme(double* slice, size_t len);

And the call from Go has now changed as well 来自Go的电话现在也发生了变化

func CallmeExternal() {
   data := make([]float64, 2, 2)
   data[0] = 1.0
   ptr := (*C.double)(unsafe.Pointer(&data[0]))
   len := C.size_t(len(data))
   size := C.callme(ptr, len)

   printf("size %v",size)
}

This returns 2 . 这返回2

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM