Giter Site home page Giter Site logo

safer-ffi-gen's People

Contributors

stefunctional avatar tomleavy avatar

Stargazers

 avatar  avatar

Watchers

 avatar

safer-ffi-gen's Issues

Fix invocation requirements

safer_ffi_gen should be able to be used in all cases. It is a no-op when called within a module that is also marked.

Currently using safer_ffi_gen_func as a marker just to get things started

Investigate compatibility with maybe-async

safer_ffi_gen looks at the async keyword on functions before maybe_async has a chance to remove it if building with the is_sync feature. This causes the function generated by safer_ffi_gen to forward incorrectly the call to the original function as if it were async.

Describe ownership of parameters and return value in documentation of generated functions

C functions generated by safer-ffi-gen may take or return pointers, but it is not clear when these pointers transfer ownership. E.g.:

  • Should the caller free the pointer returned by a function?
  • Can a pointer passed to a function be used after the call, or does the function take ownership of the pointee?

While this information is lost in the C signatures, it is present in the Rust signatures (borrows vs owned values), so it seems that it should be possible to extract it and add it to the documentation of the generated C functions.

Support non-blocking async via `tokio`

A C callback should be fired when tokio_spawn is done with the inner function that contains a custom result type if needed that can help users understand if there was an error or not.

Alternative:

on_success and on_failure

Support enumerations with data

It should be possible to expose them as an opaque type (not exposing the variants as safer-ffi does for C-like enums). Probably blocked on support in safer-ffi unless we try to implement ReprC ourselves.

Support conditional compilation for `impl` blocks

Problem

To expose functions through FFI, safer-ffi-gen requires adding the attribute macro safer_ffi_gen to the impl block and to annotate each function to expose with #[safer_ffi_gen], i.e.:

#[safer_ffi_gen]
impl Foo {
    #[safer_ffi_gen]
    pub fn foo() {}

    pub fn bar() {}
}

In the above example, foo is exposed through FFI but bar isn't. Note that while #[safer_ffi_gen] on each function looks like an attribute macro, it isn't. It is just an arbitrary token list that is recognized and removed by the #[safer_ffi_gen] macro call on the impl block.

This setup falls apart when making the FFI support conditionally compiled. First failed attempt:

#[cfg_attr(feature = "ffi", safer_ffi_gen)]
impl Foo {
    #[safer_ffi_gen]
    pub fn foo() {}

    pub fn bar() {}
}

When the ffi feature is off, the annotation on foo isn't removed and thus the code does not compile. Second failed attempt:

#[cfg_attr(feature = "ffi", safer_ffi_gen)]
impl Foo {
    #[cfg_attr(feature = "ffi", safer_ffi_gen)]
    pub fn foo() {}

    pub fn bar() {}
}

This fails to compile because the outer safer_ffi_gen attribute only recognizes functions marked exactly with #[safer_ffi_gen]. So in this case it leaves the inner cfg_attr as-is, and that causes the inner safer_ffi_gen macro to run on the fn foo function, which leads to an error because this macro is meant to be applied to an impl block instead of a function. Despite looking identical, #[safer_ffi_gen] on a function is only an arbitrary marker to be consumed by the #[safer_ffi_gen] macro on the impl block.

Solutions

The attribute on the impl block is required because this is the only way to get the type name and generics.

Solution 1

The marker on functions could be removed and all functions in an impl block with the attribute #[safer_ffi_gen] would be exposed through FFI. The drawback of this approach is that it forces users to segregate functions in different impl blocks based on whether they needs to be exposed through FFI. That can be a more invasive change for an existing codebase. An advantage of this solution is that it is easier to add to the existing safer-ffi-gen implementation.

#[cfg_attr(feature = "ffi", safer_ffi_gen)]
impl Foo {
    pub fn foo() {}
}

impl Foo {
    pub fn bar() {}
}

Solution 2

The safer_ffi_gen macro could be changed to handle both an impl block and a function. When given an impl block, it would inject the type name and generics into the safer_ffi_gen attribute on functions inside the impl block. This solution requires more work but provides more flexibility to users to arrange their functions.

The code would be written as follows:

#[cfg_attr(feature = "ffi", safer_ffi_gen)]
impl Foo {
    #[cfg_attr(feature = "ffi", safer_ffi_gen)]
    pub fn foo() {}

    pub fn bar() {}
}

The expansion of the outer attribute would give something like:

impl Foo {
    #[cfg_attr(feature = "ffi", safer_ffi_gen(Foo)]
    pub fn foo() {}

    pub fn bar() {}
}

Convert receiver to ffi type

Currently receivers &self self etc are not supported. These should be converted to parameters of the FFI method

Support convert `Result<T>` into `Out`

The pattern for a result should be a function that has any output as Out and the function returns c_int.

There should also be a thread local err that you can get an error message from as a string with a function call

Fix `#[repr(transparent)]` support

It seems to be limited to types with a niche (e.g. Box<T>) in safer-ffi 0.0.10. 0.1.0-rc1 addresses that, so let's try to update when it gets officially released. Support in safer-ffi-gen should already be implemented, so this task is mainly/entirely about adding a test.

Consider supporting a custom prefix for generated identifiers

In C, functions and types defined by a library often share a custom prefix identifying the library (thus emulating namespaces and avoiding name collisions). It would be helpful to support this.

An easy way is to specify this prefix everywhere one of our macros is used, but being able to define this prefix once and have it applied everywhere would be nice.

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.