Reputation: 103
I was trying to build a simple rust rss 'harvester' for my soup.io blog and then post those entries to diaspora with node.js (since there is an npm package for that)
I want to learn how to use rust from node so this is why I'm building this project.
My problem is that I don't know how to call the ffi
function with the right types.
var lib = ffi.Library('target/debug/libmain', {
'get_soup': ['Vec<Post>', ['String']]
});
The 'Vec<Post>'
doesn't work.
I get that I have to use ref
for that.
But I don't really know how and what that actually does.
I understand that I have to translate the rust types to javascript?
How can I use Vec<Post>
in my ffi function?
my github project for that: Realtin/suppe
and here the relevant code:
extern crate rss;
extern crate hyper;
use rss::Rss;
use std::io::prelude::*;
#[derive(Debug)]
pub struct Post {
title: String,
link: String,
description: String,
}
fn main() {
let user = "realtin".to_string();
let vec = get_soup(&user);
println!("{:?}", vec[vec.len()-1]);
}
#[no_mangle]
pub extern fn get_soup(user: &str) ->Vec<Post>{
let url = format!("http://{}.soup.io/rss", user);
let mut vec = Vec::new();
let client = hyper::Client::new();
let mut response = client.get(&url).send().unwrap();
let mut suppe = String::new();
let _= response.read_to_string(&mut suppe);
let rss::Rss(channel) = suppe.parse::<rss::Rss>().unwrap();
for item in channel.items.into_iter().rev() {
let item_object = Post {
title: item.title.unwrap(),
link: item.link.unwrap(),
description: item.description.unwrap(),
};
vec.push(item_object);
}
return vec;
}
var ref = require('ref');
var StructType = require("ref-struct");
var ffi = require('ffi');
var Post = StructType({
title: String,
link: String,
description: String,
});
// var vecPost = ref.refType(ref.types.Object);
var lib = ffi.Library('target/debug/libmain', {
'get_soup': ['Vec<Post>', ['String']]
});
var posts = lib.get_soup("realtin");
Upvotes: 10
Views: 4493
Reputation: 13889
Some data types can be passed directly, using your approach
Export Rust using FFI https://svartalf.info/posts/2019-03-01-exposing-ffi-from-the-rust-library/
and then call it from nodejs from using something like https://github.com/node-ffi/node-ffi
May be not using structure that you require, but you can convert data in one or both ends. As a last resort you can use JSON. There will be some overhead but not a lot
https://stackoverflow.com/a/42498913/3232611
can use protocol buffers, if JSON performance is bottleneck, but in most cases its not worth complexity
Upvotes: -1
Reputation: 299810
The short answer: you cannot export any Rust function for FFI bindings, you need to specifically export Rust functions compatible with C.
Specifically, this means that you need to expose only C-struct compatible objects OR expose opaque pointers (which can only be manipulated through Rust functions).
In your case, Vec<Post>
is not compatible with usage in FFI, because Vec
is not.
You can find more information in the FFI Guide.
Upvotes: 10