Warning
This post was published 55 days ago. The information described in this article may have changed.
While learning Rust, the question of how to connect Rust to Perl inevitably came up. One possibility via FFi is FFI::Platypus::Lang::Rust:
use anyhow::{Context, Result};
use num_bigint::BigUint;
use std::slice;
fn frob(n: u64) -> Result<BigUint> {
Ok((1..=n)
.into_iter()
.map(|i| BigUint::from(i))
.reduce(|a, b| a * b)
.context("fuba")?)
}
#[unsafe(no_mangle)]
pub extern "C"
fn get_frob(len: *mut usize, n: u64) -> *const u8 {
let big = frob(n).unwrap();
let bytes = big.to_bytes_be();
let boxed_slice = bytes.into_boxed_slice();
let gizmo = boxed_slice.as_ptr();
let length = boxed_slice.len();
std::mem::forget(boxed_slice);
unsafe {
if !len.is_null() {
*len = length;
}
}
gizmo
}
#[unsafe(no_mangle)]
pub extern "C"
fn free_frob(gizmo: *mut u8, len: usize) {
unsafe {
let _ =
Box::from_raw(slice::from_raw_parts_mut(gizmo, len));
}
}
#[cfg(test)]
mod testomato {
use super::*;
#[test]
fn check_get_frob() {
let mut n: usize = 0;
let len = &mut n;
let gizmo = get_frob(len, 3_u64);
assert!(6 == unsafe { *gizmo });
}
#[test]
fn check_frob()->Result<()> {
let result = frob(3_u64)?;
assert!(BigUint::from(6u64) == result);
Ok(())
}
}
The fact that this code works does not necessarily mean that it is correct. However, it works quite well. Here is the corresponding part in Perl:
#/usr/bin/env perl
use strict;
use warnings;
use FFI::Platypus 2.00;
use FFI::Platypus::Buffer qw( buffer_to_scalar );
use Data::Dump;
use Math::BigInt;
use feature qw(say);
my $ffi = FFI::Platypus->new( api => 2, lang => 'Rust' );
$ffi->lib('../target/release/libacme.so');
$ffi->attach( get_frob => [ 'usize*', 'u64' ] => 'opaque' );
$ffi->attach( free_frob => [ 'opaque', 'usize' ] => 'void' );
my $n = shift || 1000;
my $length = 0;
my $gizmo = get_frob( \$length, $n );
my $bytes = buffer_to_scalar( $gizmo, $length );
# dd $bytes;
# dd $length;
my $bigint = Math::BigInt->from_bytes($bytes);
# dd $bigint;
say $bigint;
free_frob( $gizmo, $length );
__END__
I followed the friendly manuals - less or more. Thanks for any advice and hint (preferably on the Rust part).
1 post - 1 participant
🏷️ rust_feed