duanrong0738 2017-11-02 12:08
浏览 212
已采纳

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

I want to call some external functions written in Rust from Go with a reference to a slice.

I have the following Rust code:

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:

#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:

//#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

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?

  • 写回答

1条回答 默认 最新

  • dongqi4085 2017-11-02 12:31
    关注

    According to The Rust FFI Omnibus as provided by @matthieu-m, I have successfully rewritten the code. The function signature must accept the types understood by the target language.

    The Rust function signature changed to:

    #[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

    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.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 安卓adb backup备份应用数据失败
  • ¥15 eclipse运行项目时遇到的问题
  • ¥15 关于#c##的问题:最近需要用CAT工具Trados进行一些开发
  • ¥15 南大pa1 小游戏没有界面,并且报了如下错误,尝试过换显卡驱动,但是好像不行
  • ¥15 没有证书,nginx怎么反向代理到只能接受https的公网网站
  • ¥50 成都蓉城足球俱乐部小程序抢票
  • ¥15 yolov7训练自己的数据集
  • ¥15 esp8266与51单片机连接问题(标签-单片机|关键词-串口)(相关搜索:51单片机|单片机|测试代码)
  • ¥15 电力市场出清matlab yalmip kkt 双层优化问题
  • ¥30 ros小车路径规划实现不了,如何解决?(操作系统-ubuntu)