struct Foo { ... }
fn create_foo() -> Foo {
let foo = Foo { ... };
foo
}| mod sys; | |
| use std::ffi::CString; | |
| use std::os::raw::c_void; | |
| use std::{thread, time::Duration}; | |
| // A macro to print the function name | |
| macro_rules! function { | |
| () => {{ | |
| fn f() {} |
| all: | |
| # Build a static library from the Rust file | |
| rustc --crate-type=staticlib ext.rs | |
| # Compile the C file with the static library | |
| # gcc -o sample-c sample.c libext.a | |
| gcc -o sample sample.c -L. -lext | |
| ./sample | |
| clean: | |
| rm libext.a | |
| rm sample |
| // A module containing all the types and APIs in the external library. | |
| mod sys { | |
| use std::cmp; | |
| use std::ffi::CString; | |
| use std::os::raw::{c_char, c_void}; | |
| pub type XString = *mut c_void; | |
| extern "C" { | |
| fn calloc(items: usize, size: usize) -> *mut c_void; |
| all: | |
| # Sample in C(static library): | |
| # gcc -c string_ref.c -o string_ref.o | |
| # ar rcs libstringref.a string_ref.o | |
| # gcc -c device.c -o device.o | |
| # ar rcs libdevice.a device.o | |
| # gcc sample.c -L. -ldevice -lstringref -o sample-c | |
| # ./sample-c | |
| # Sample in C: |
| all: | |
| # Build a static library from the Rust file | |
| rustc --crate-type=staticlib ext.rs | |
| # Compile the C file with the static library | |
| # gcc -o sample-c sample.c libext.a | |
| gcc -o sample-c sample.c -L. -lext | |
| ./sample-c | |
| # g++ -o sample-cpp sample.cpp libext.a | |
| g++ -o sample-cpp sample.cpp -L. -lext | |
| ./sample-cpp |
The key point for this gist repo is to indicate:
Don't misuse the pointers of the instances allocated in functions stack since they will be gone after finishing the function calling.
The sample code here is to demonstrate the problem I have when I am developing a [Rust audio library][draft]. To play sounds, it needs to register callbacks to the underlying OS through audio APIs and then the callbacks will be fired periodically. The callback usually will come with at least 2 parameters:
- a buffer that will be filled with audio data
- a pointer indicating what variable calls the callback.
To create Rust APIs that can play audio, I create a struct for audio stream named Stream and store all the stream related settings like sampling rate or channels in that struct. There is a struct method named new that will create a Stream instance that will be returnd. Before the instance is returned, I use the pointer of
| #[path = ""] | |
| mod utils { | |
| #[path = "audio_object.rs"] | |
| mod audio_object; | |
| use self::audio_object::{get_property_data, sys::*}; | |
| use std::fmt; // For fmt::{Display, Formatter, Formatter} | |
| #[derive(PartialEq)] | |
| pub enum Scope { |
| all: | |
| # Sample in C: | |
| # gcc -shared -fPIC device.c -o libdevice.so | |
| # gcc sample.c libdevice.so -o sample-c | |
| # ./sample-c | |
| # Sample in C++: | |
| g++ -std=c++11 -shared -fPIC device.cpp -o libdevice.so | |
| g++ -std=c++11 sample.cpp libdevice.so -o sample-cpp | |
| ./sample-cpp |
| #include <cassert> | |
| typedef int NewType; | |
| struct A { | |
| NewType a; | |
| }; | |
| struct B { | |
| NewType b; |