Code Monkey home page Code Monkey logo

rust-ffi-examples's Introduction

Rust FFI Examples

This is an example repository that shows how to interface between Rust and a various number of other languages.

At this time, though, I unfortunately don't have time to continue maintaining this so I'm going to archive the repository. Thanks to everyone for contributing!

rust-ffi-examples's People

Contributors

alexcrichton avatar antiarchitect avatar billpmurphy avatar bsqql123 avatar ehsanmok avatar gmiroshnykov avatar hako avatar itanq avatar ivanovaleksey avatar livioribeiro avatar lucis-fluxum avatar miehe-dup avatar return avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

rust-ffi-examples's Issues

Rust-to-C : Adding pre compiled archive file

Hi,
I see that we can add individual source files, compile those files, create a library and then link it. If we have a huge number of source files then it's bit cumbersome to add individual files.
But for example if I already have an archive file precompiled for a set of C source files then how to link it.

Just for testing, after initial build I replaced libdouble.a with my precompiled archive file with same name and it works.

So it would be great if there's any way to link already existing static archive. Any suggestions?

Thanks.

Passing strings from and to lua

I have been trying to adapt the example https://github.com/alexcrichton/rust-ffi-examples/blob/master/luajit-to-rust/src/lib.rs to use strings instead of i32s.

pub extern fn really_useful_string_transformation(subject: &str) -> &str {
  return subject;
}

//lua
  ffi.cdef[[
  const char* really_useful_string_transformation(const char* subject);
  ]]
  local really_useful_string_transformation = ffi.load('...').really_useful_string_transformation
  ngx.say(ffi.string(really_useful_string_transformation("peter")))

This works, but if I want to transform subject, I need to return String in rust instead of the pointer. But what is the corresponding return type that I declare in lua?

pub extern fn really_useful_string_transformation(subject: &str) -> String {
  return subject.to_string();
}

//lua
  ffi.cdef[[
  const --WHAT GOES HERE?-- really_useful_string_transformation(const char* subject);
  ]]
  local really_useful_string_transformation = ffi.load('...').really_useful_string_transformation
  ngx.say(really_useful_string_transformation("peter"))

c-to-rust example fails

Hi

I'm on Ubuntu 14.04, gcc --version 4.8.4, rustc stable 1.25. Running make for c-to-rust example fails with:

mkdir -p target
cc -o target/main.o -c src/main.c
cargo build
   Compiling c-to-rust v0.1.0 (file:///home/ehsan/Rust/rust-ffi-examples/c-to-rust)
    Finished dev [unoptimized + debuginfo] target(s) in 0.20 secs
cc -o target/double target/main.o target/debug/libdouble_input.a -Wl,--gc-sections -lpthread
target/debug/libdouble_input.a(std-c10c01f750e28d27.std0.rcgu.o): In function `std::sys::unix::backtrace::printing::dladdr::resolve_symname::hd51038292556fc5f':
/checkout/src/libstd/sys/unix/backtrace/printing/dladdr.rs:25: undefined reference to `dladdr'
target/debug/libdouble_input.a(std-c10c01f750e28d27.std0.rcgu.o): In function `std::sys::unix::backtrace::printing::dladdr::resolve_symname::hc193d8ebb6be498a':
/checkout/src/libstd/sys/unix/backtrace/printing/dladdr.rs:25: undefined reference to `dladdr'
collect2: error: ld returned 1 exit status
make: *** [target/double] Error 1

I couldn't find what the error is referring to "undefined reference to `dladdr'".
Any idea?
Thanks

Error when running python-to-rust

When running the Makefile in python-to-rust, I get the following error:

▶ make
cargo build
   Compiling python-to-rust v0.1.0 (file:///Users/andy/Documents/playground/rust-ffi-examples/python-to-rust)
(cd target && ln -nsf debug/libdouble_input-*dylib libdouble_input.so)
python src/main.py
Traceback (most recent call last):
  File "src/main.py", line 3, in <module>
    lib = cdll.LoadLibrary('target/libdouble_input.so')
  File "/Users/andy/miniconda/lib/python2.7/ctypes/__init__.py", line 443, in LoadLibrary
    return self._dlltype(name)
  File "/Users/andy/miniconda/lib/python2.7/ctypes/__init__.py", line 365, in __init__
    self._handle = _dlopen(self._name, mode)
OSError: dlopen(target/libdouble_input.so, 6): image not found
make: *** [all] Error 1

This happens for Python 2.7 as well as 3.4 with Rust 1.0

Any ideas? :)

c-to-rust lack of rust cleanup?

Hi,

From what I can gather, it appears that when C code (and possibly anything else) is calling into rust code, the rust code will never have its cleanup routines run. This results in things like io::stdio::stdout() (and possibly a bunch of other things) allocating space and setting up resources that are never freed and torn down, respectively. Given that this has to do with the fact that rust isn't actually the main executable with a single entry point, it seems that this task of calling the cleanup has to be done from C. Is there a good way to do that?

#![crate_type = "staticlib"]

#[no_mangle]
pub extern fn double_input(input: i32) -> i32 {
    println!("{} {}", "hello world: ", input);
    input * 2
}
$ rustc --version
rustc 1.0.0 (a59de37e9 2015-05-13) (built 2015-05-14)
$ valgrind --leak-check=full --show-leak-kinds=all ./target/double
==15247== Memcheck, a memory error detector
==15247== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==15247== Using Valgrind-3.10.0.SVN and LibVEX; rerun with -h for copyright info
==15247== Command: ./target/double
==15247== 
hello world:  4
4 * 2 = 8
==15247== 
==15247== HEAP SUMMARY:
==15247==     in use at exit: 1,288 bytes in 8 blocks
==15247==   total heap usage: 9 allocs, 1 frees, 1,320 bytes allocated
==15247== 
==15247== 8 bytes in 1 blocks are still reachable in loss record 1 of 8
==15247==    at 0x40B0D2: je_mallocx (in /home/jtd/rs/rust-ffi-examples/c-to-rust/target/double)
==15247==    by 0x404127: io::stdio::stdout::h9a5de2f312c7844aCMg (in /home/jtd/rs/rust-ffi-examples/c-to-rust/target/double)
==15247==    by 0x405AF4: io::stdio::_print::ha1d8e66e312be5295Tg (in /home/jtd/rs/rust-ffi-examples/c-to-rust/target/double)
==15247==    by 0x401BD7: double_input::__rust_abi (<std macros>:2)
==15247==    by 0x401AB7: double_input (in /home/jtd/rs/rust-ffi-examples/c-to-rust/target/double)
==15247==    by 0x401A5E: main (in /home/jtd/rs/rust-ffi-examples/c-to-rust/target/double)
==15247== 
==15247== 8 bytes in 1 blocks are still reachable in loss record 2 of 8
==15247==    at 0x40B0D2: je_mallocx (in /home/jtd/rs/rust-ffi-examples/c-to-rust/target/double)
==15247==    by 0x404A0D: io::stdio::stdout::stdout_init::hf0a88977d03b8f3f3Mg (in /home/jtd/rs/rust-ffi-examples/c-to-rust/target/double)
==15247==    by 0x40415A: io::stdio::stdout::h9a5de2f312c7844aCMg (in /home/jtd/rs/rust-ffi-examples/c-to-rust/target/double)
==15247==    by 0x405AF4: io::stdio::_print::ha1d8e66e312be5295Tg (in /home/jtd/rs/rust-ffi-examples/c-to-rust/target/double)
==15247==    by 0x401BD7: double_input::__rust_abi (<std macros>:2)
==15247==    by 0x401AB7: double_input (in /home/jtd/rs/rust-ffi-examples/c-to-rust/target/double)
==15247==    by 0x401A5E: main (in /home/jtd/rs/rust-ffi-examples/c-to-rust/target/double)
==15247== 
==15247== 8 bytes in 1 blocks are still reachable in loss record 3 of 8
==15247==    at 0x40B0D2: je_mallocx (in /home/jtd/rs/rust-ffi-examples/c-to-rust/target/double)
==15247==    by 0x40417C: io::stdio::stdout::h9a5de2f312c7844aCMg (in /home/jtd/rs/rust-ffi-examples/c-to-rust/target/double)
==15247==    by 0x405AF4: io::stdio::_print::ha1d8e66e312be5295Tg (in /home/jtd/rs/rust-ffi-examples/c-to-rust/target/double)
==15247==    by 0x401BD7: double_input::__rust_abi (<std macros>:2)
==15247==    by 0x401AB7: double_input (in /home/jtd/rs/rust-ffi-examples/c-to-rust/target/double)
==15247==    by 0x401A5E: main (in /home/jtd/rs/rust-ffi-examples/c-to-rust/target/double)
==15247== 
==15247== 32 bytes in 1 blocks are still reachable in loss record 4 of 8
==15247==    at 0x40B0D2: je_mallocx (in /home/jtd/rs/rust-ffi-examples/c-to-rust/target/double)
==15247==    by 0x403F3B: rt::at_exit_imp::push::h8b92b68766e7993dZiw (in /home/jtd/rs/rust-ffi-examples/c-to-rust/target/double)
==15247==    by 0x40414E: io::stdio::stdout::h9a5de2f312c7844aCMg (in /home/jtd/rs/rust-ffi-examples/c-to-rust/target/double)
==15247==    by 0x405AF4: io::stdio::_print::ha1d8e66e312be5295Tg (in /home/jtd/rs/rust-ffi-examples/c-to-rust/target/double)
==15247==    by 0x401BD7: double_input::__rust_abi (<std macros>:2)
==15247==    by 0x401AB7: double_input (in /home/jtd/rs/rust-ffi-examples/c-to-rust/target/double)
==15247==    by 0x401A5E: main (in /home/jtd/rs/rust-ffi-examples/c-to-rust/target/double)
==15247== 
==15247== 48 bytes in 1 blocks are still reachable in loss record 5 of 8
==15247==    at 0x40B0D2: je_mallocx (in /home/jtd/rs/rust-ffi-examples/c-to-rust/target/double)
==15247==    by 0x404BD7: sys::mutex::ReentrantMutex::new::h9030e93b64febd67dzt (in /home/jtd/rs/rust-ffi-examples/c-to-rust/target/double)
==15247==    by 0x404A1E: io::stdio::stdout::stdout_init::hf0a88977d03b8f3f3Mg (in /home/jtd/rs/rust-ffi-examples/c-to-rust/target/double)
==15247==    by 0x40415A: io::stdio::stdout::h9a5de2f312c7844aCMg (in /home/jtd/rs/rust-ffi-examples/c-to-rust/target/double)
==15247==    by 0x405AF4: io::stdio::_print::ha1d8e66e312be5295Tg (in /home/jtd/rs/rust-ffi-examples/c-to-rust/target/double)
==15247==    by 0x401BD7: double_input::__rust_abi (<std macros>:2)
==15247==    by 0x401AB7: double_input (in /home/jtd/rs/rust-ffi-examples/c-to-rust/target/double)
==15247==    by 0x401A5E: main (in /home/jtd/rs/rust-ffi-examples/c-to-rust/target/double)
==15247== 
==15247== 64 bytes in 1 blocks are still reachable in loss record 6 of 8
==15247==    at 0x40B0D2: je_mallocx (in /home/jtd/rs/rust-ffi-examples/c-to-rust/target/double)
==15247==    by 0x409815: vec::Vec$LT$T$GT$::push::resize::h13970319319561877210 (in /home/jtd/rs/rust-ffi-examples/c-to-rust/target/double)
==15247==    by 0x403F80: rt::at_exit_imp::push::h8b92b68766e7993dZiw (in /home/jtd/rs/rust-ffi-examples/c-to-rust/target/double)
==15247==    by 0x40414E: io::stdio::stdout::h9a5de2f312c7844aCMg (in /home/jtd/rs/rust-ffi-examples/c-to-rust/target/double)
==15247==    by 0x405AF4: io::stdio::_print::ha1d8e66e312be5295Tg (in /home/jtd/rs/rust-ffi-examples/c-to-rust/target/double)
==15247==    by 0x401BD7: double_input::__rust_abi (<std macros>:2)
==15247==    by 0x401AB7: double_input (in /home/jtd/rs/rust-ffi-examples/c-to-rust/target/double)
==15247==    by 0x401A5E: main (in /home/jtd/rs/rust-ffi-examples/c-to-rust/target/double)
==15247== 
==15247== 96 bytes in 1 blocks are still reachable in loss record 7 of 8
==15247==    at 0x40B0D2: je_mallocx (in /home/jtd/rs/rust-ffi-examples/c-to-rust/target/double)
==15247==    by 0x404A8B: io::stdio::stdout::stdout_init::hf0a88977d03b8f3f3Mg (in /home/jtd/rs/rust-ffi-examples/c-to-rust/target/double)
==15247==    by 0x40415A: io::stdio::stdout::h9a5de2f312c7844aCMg (in /home/jtd/rs/rust-ffi-examples/c-to-rust/target/double)
==15247==    by 0x405AF4: io::stdio::_print::ha1d8e66e312be5295Tg (in /home/jtd/rs/rust-ffi-examples/c-to-rust/target/double)
==15247==    by 0x401BD7: double_input::__rust_abi (<std macros>:2)
==15247==    by 0x401AB7: double_input (in /home/jtd/rs/rust-ffi-examples/c-to-rust/target/double)
==15247==    by 0x401A5E: main (in /home/jtd/rs/rust-ffi-examples/c-to-rust/target/double)
==15247== 
==15247== 1,024 bytes in 1 blocks are still reachable in loss record 8 of 8
==15247==    at 0x40B0D2: je_mallocx (in /home/jtd/rs/rust-ffi-examples/c-to-rust/target/double)
==15247==    by 0x404923: io::stdio::stdout::stdout_init::hf0a88977d03b8f3f3Mg (in /home/jtd/rs/rust-ffi-examples/c-to-rust/target/double)
==15247==    by 0x40415A: io::stdio::stdout::h9a5de2f312c7844aCMg (in /home/jtd/rs/rust-ffi-examples/c-to-rust/target/double)
==15247==    by 0x405AF4: io::stdio::_print::ha1d8e66e312be5295Tg (in /home/jtd/rs/rust-ffi-examples/c-to-rust/target/double)
==15247==    by 0x401BD7: double_input::__rust_abi (<std macros>:2)
==15247==    by 0x401AB7: double_input (in /home/jtd/rs/rust-ffi-examples/c-to-rust/target/double)
==15247==    by 0x401A5E: main (in /home/jtd/rs/rust-ffi-examples/c-to-rust/target/double)
==15247== 
==15247== LEAK SUMMARY:
==15247==    definitely lost: 0 bytes in 0 blocks
==15247==    indirectly lost: 0 bytes in 0 blocks
==15247==      possibly lost: 0 bytes in 0 blocks
==15247==    still reachable: 1,288 bytes in 8 blocks
==15247==         suppressed: 0 bytes in 0 blocks
==15247== 
==15247== For counts of detected and suppressed errors, rerun with: -v
==15247== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

golang ?

I am looking for a good way to do golang to rust FFI both ways.

If anyone has suggestions it would be great. golang is made to call c using cgo, which is very very slow. its golangs fault.
SO thats one way, but perf is really bad.

what else to do to get decent perf and easy of development ?

python-to-rust string example needed

After two days of searching and asking questions I finally figured out how to make Python talk to Rust using something more than a simple i32 -> i32 function. No one has a basic example dealing with String, CString, or libc::c_char. I would love to see an example with a function signature kinda like this:

Rust:

extern crate libc;
use libc::{c_char};

#[no_mangle]
pub extern fn say_hello(name: *const c_char) -> *const c_char {
    // ...Handle string from Python,
    //    possibly use the string with Rust libs like Regex or Path..
    //    return a new string built with Rust (preferably in  "safe" manner)
}

Python:

from cffi import FFI
ffi = FFI()

rustlib = ffi.dlopen('myrustlib.so')

ffi.cdef("""
    char* say_hello(const char *n);
""")

# `myname` could come from anywhere, possibly user arguments.
myname = 'cj'
# Python3, the library is expecting bytes.
name = ffi.new('char[]', bytes(myname, 'utf-8'))

# Again Python3, we'll get bytes back so they need to be decoded.
msg = ffi.string(rustlib.say_hello(name)).decode('utf-8')
print('Rust said: {}'.format(msg))

I haven't tested this snippet, but it looks like what I was using. I don't even know if this is the idiomatic way to do this because I'm new to rust/c/c++, but *const c_char was the only thing that would work without segfaulting. The problem is I don't know if I am managing memory correctly in my original test library or if there is a better way to achieve the same thing. I'm converting from *const c_char to String so Rust can display or use the original arguments. Regex and Path need rust strings to work with.

The Rust Once, Run Everywhere post showed up right after I tackled this issue on my own. It would be awesome if someone that actually knew what they were doing could write about the use of c strings with Python/Rust.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.