Home > Article > Backend Development > Callback functions from Rust to Go
I'm trying to create the possibility to call a rust function from go and then said rust function calls back the function to go. I'm using cgo as the ffi interface between go and rust. The following is my go code (src/main.go):
package main import ( "c" "fmt" "unsafe" ) /* #cgo cflags: -i./../lib #cgo ldflags: -l./../bin -lgo_move -wl,-rpath=./bin #include "move.h" */ //export cosmoscallbackwrapper func cosmoscallbackwrapper(data *c.uchar, datalen c.int) { // convert data to go slice godata := c.gobytes(unsafe.pointer(data), datalen) // call the actual callback function cosmoscallback(godata) } // setcosmoscallback sets the callback function to be called by the move vm. func setcosmoscallback(callback func([]byte)) { cosmoscallback = callback c.set_cosmos_callback((c.cosmos_callback)(unsafe.pointer(c.cosmoscallbackwrapper))) } var cosmoscallback func([]byte) func main() { // create a new move interpreter // set the callback function setcosmoscallback(func(data []byte) { fmt.println("received data from move vm:", data) // handle data and call cosmos sdk functions as needed }) }
This is my rust code (src/lib.rs)
use std::os::raw::{c_char, c_int}; use std::ffi::cstring; use std::sync::mutex; #[macro_use] extern crate lazy_static; pub fn main() { } pub type cosmoscallback = extern "c" fn(*const c_char, c_int); lazy_static! { static ref callback: mutex<option<cosmoscallback>> = mutex::new(none); } #[no_mangle] pub extern "c" fn set_cosmos_callback(callback: cosmoscallback) { let mut cb = callback.lock().unwrap(); *cb = some(callback); } #[no_mangle] pub extern "c" fn cosmoscallbackwrapper(data: *const c_char, data_len: c_int) { let cb = callback.lock().unwrap(); if let some(callback) = &*cb { callback(data, data_len); } }
This is my cargo.toml file:
[package] name = "go-move" version = "0.1.0" edition = "2021" [lib] crate-type = ["cdylib"] [dependencies] libc = "0.2" lazy_static = "1.4.0" [workspace] members = [ ".",]
This is lib/move.h (header file of shared library):
#ifndef move_vm_lib_h #define move_vm_lib_h #include <stdint.h> //typedef void (*cosmos_callback)(const unsigned char *data, int data_len); //void set_cosmos_callback(cosmos_callback callback); typedef void (*cosmos_callback)(const uint8_t* data, int32_t data_len); void set_cosmos_callback(cosmos_callback callback); #endif
This is my makefile:
shell := /bin/bash .phony: build os = $(shell uname) clean: rm -rf bin rm -rf target build: @echo the os is $(os) mkdir bin cargo build --release ifeq ($(os),linux) cp target/release/libgo_move.so bin/ else cp target/release/libgo_move.dylib bin/ endif cp -a lib/. bin/ go build --ldflags="-l./bin -lgo_move" -o bin/main src/main.go run: export ld_library_path=./bin && ./main
The file structure is as follows:
src main.go main.rs bin libgo_move.so (after cargo build) lib move.h cargo.toml makefile
After running make clean build
I get the following output:
cp target/release/libgo_move.so bin/ cp -a lib/. bin/ go build -o bin/main src/main.go # command-line-arguments src/main.go:27:59: could not determine kind of name for C.cosmosCallbackWrapper src/main.go:27:25: could not determine kind of name for C.cosmos_callback src/main.go:27:2: could not determine kind of name for C.set_cosmos_callback
For some reason it can't find the ffi function.
This is a stupid mistake:
/* #cgo CFLAGS: -I./../lib #cgo LDFLAGS: -L./../bin -lgo_move -Wl,-rpath=./bin #include "move.h" */
Must be done before importing. That's all.
The above is the detailed content of Callback functions from Rust to Go. For more information, please follow other related articles on the PHP Chinese website!