Code Monkey home page Code Monkey logo

Comments (3)

fredszaq avatar fredszaq commented on August 24, 2024 1

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 that AsRust 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 the Dict if you really need AsRust but you probably want to just borrow the dict (take a look at the RawBorrow trait)

from ffi-convert-rs.

fredszaq avatar fredszaq commented on August 24, 2024

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.

Maddin-619 avatar Maddin-619 commented on August 24, 2024

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)

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.