Comments (3)
I you want Dict
to be opaque, no need to declare a CDict, you would however manually implement CReprOf
and AsRust
on CIodd
.
Something a bit like this:
use ffi_convert::{CDrop, CReprOf, RawPointerConverter, CStringArray};
pub struct Iodd {
pub device_id: u32,
pub vendor_id: u16,
pub languages: Vec<String>,
pub i18n_dict: Dict,
}
#[derive(CDrop, RawPointerConverter)]
pub struct Dict {
_whatever: String
}
#[repr(C)]
#[derive(CDrop, RawPointerConverter)]
pub struct CIodd {
pub device_id: u32,
pub vendor_id: u16,
pub languages: CStringArray,
pub i18n_dict: *const Dict
}
impl CReprOf<Iodd> for CIodd {
fn c_repr_of(input: Iodd) -> Result<Self, ffi_convert::CReprOfError> {
Ok(Self {
device_id: input.device_id,
vendor_id: input.vendor_id,
languages: CStringArray::c_repr_of(input.languages)?,
i18n_dict: input.i18n_dict.into_raw_pointer()
})
}
}
#[no_mangle]
pub extern "C" fn init_iodd(_: *mut *const CIodd) {
// whatever
}
#[no_mangle]
pub extern "C" fn drop_iodd(iodd: *const CIodd) {
unsafe { CIodd::drop_raw_pointer(iodd) }.unwrap() // probably want a better error handling
}
which when passed to cbindgen -d
gives us this
#include <cstdarg>
#include <cstdint>
#include <cstdlib>
#include <ostream>
#include <new>
struct Dict;
/// A utility type to represent arrays of string
/// # Example
///
/// ```
/// use ffi_convert::{CReprOf, CStringArray};
/// let pizza_names = vec!["Diavola".to_string(), "Margarita".to_string(), "Regina".to_string()];
/// let c_pizza_names = CStringArray::c_repr_of(pizza_names).expect("could not convert !");
///
/// ```
struct CStringArray {
/// Pointer to the first element of the array
const char *const *data;
/// Number of elements in the array
uintptr_t size;
};
struct CIodd {
uint32_t device_id;
uint16_t vendor_id;
CStringArray languages;
const Dict *i18n_dict;
};
extern "C" {
void init_iodd(const CIodd**);
void drop_iodd(const CIodd *iodd);
} // extern "C"
Dict
is properly declared as an opaque struct
a few notes:
- I used the
CStringArray
here because is was easier, not a big fan of using this type as this can lead to ugly stuff when generating the headers... as you can see we get rust doc in the .h, but more importantly the struct is I find named in a too generic way to be useful in the other language and it may not bit apparent in C that this comes from your lib..., consider copying the type in your code and rename it accordingly (this way you don't need to pass-d
to cbindgen as well CIodd
is probably not the name you want in your C header- I didn't implement
AsRust
here, the rationale being thatAsRust
makes defensive copies of everything (it is designed for data coming from C and being ingested in a rust lib), this means you can't take back ownership of the raw pointer in it. You could just deref the raw pointer and do a clone of theDict
if you really needAsRust
but you probably want to just borrow the dict (take a look at theRawBorrow
trait)
from ffi-convert-rs.
Hi @Maddin-619 ! Sorry for the late response...
Could you precise your use case ?
The custom derives for CReprOf
and AsRust
do not support opaque pointers, but you could implement the traits directly on the struct that contains the opaque pointer
from ffi-convert-rs.
I have a rust struct which I want to return to a c function call:
pub struct Iodd {
pub device_id: u32,
pub vendor_id: u16,
pub languages: Vec<String>,
pub i18n_dict: Dict,
}
I don't want to provide the whole Dict
to the caller. Instead a want an opaque pointer to it. The caller should pick a specific language and call another function providing the opaque pointer, the language and the translation key.
Would that be correct delcaring a empty CDict struct implementing the traits:
#[repr(C)]
#[derive(CDrop, RawPointerConverter)]
pub struct CDict {}
impl AsRust<Dict> for CDict {
fn as_rust(&self) -> Result<Dict, ffi_convert::AsRustError> {
let data = self as *const CDict as *const Dict;
unsafe {
let b = Box::from_raw(data as *mut Dict);
Ok(*b)
}
}
}
impl CReprOf<Dict> for CDict {
fn c_repr_of(mut _input: Dict) -> Result<Self, ffi_convert::CReprOfError> {
let data: *mut CDict = &mut _input as *mut _ as *mut CDict;
unsafe {
let b = Box::from_raw(data);
Ok(*b)
}
}
}
from ffi-convert-rs.
Related Issues (10)
- Get rid of the Failure crate
- Examples in 'ffi-convert/lib.rs' are a little unclear
- Size in CArray is int32_t? HOT 2
- Missing CReprOf impls for u8 and i8
- How to convert from c struct efficiently HOT 1
- CArray cannot exposed well to C with cbindgen HOT 1
- Add conversion for fixed size arrays HOT 12
- Make CArray 'Clone' HOT 4
- CStringArray derive [CReprOf, CDrop] error HOT 2
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
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.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from ffi-convert-rs.