最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

Achieve async FFI (swiftrust) with swift-rs crate - Stack Overflow

programmeradmin3浏览0评论

Summarize the problem

Hi all, the problem I am facing is that I am unaware how to simulate an async function through rust FFI.

I am writing a program in rust, and needed some native MacOS functions, I wrote the functions in the swift programming language using and made them public facing ie

@_cdecl("fooExported")
public func fooExported()

this works well using the swift-rs crate as it also safely converts some swift types into rust primitives. However, one of the things I am trying to accomplish is done in an async function which I cannot seem to get working as async functions (or methods idk), cannot be exposed using @_cdecl

see [#Enlightenment] for the "real" issue

Describe what you’ve tried

I did some reading and found an answer on the swift-rs issues page: which was quite helpful in getting me started, but quite frankly, my knowledge of rust is superficial, and worse in swift, so I was unsure about what was actually going on under the hood with async conversion etc.

Essentially, what I have now is the following:

//consider an async function with arg and return types
func foo(arg: Int) async -> String {
    arg.description
}

//we need a function signature that works in the C ABI
@_cdecl("fooExported")
public func fooExported(arg: Int, context: UInt64, completion: @Sendable @convention(c)(SRString,UInt64) -> ()) {

    Task {
        let r = await foo(arg: arg)
        completion(SRString(r), context)
    }
}

as shown in the issue example, and on the rust side:

#[tokio::main]
async fn main() {
    let gg = foo(1738).await;
    println!("{gg}");
}


 async fn foo(arg: i64) -> String {
    let (sender,receiver) = continuation();
    let boxed_sender = Box::new(sender);
    unsafe {
        fooExported(1337, Box::into_raw(boxed_sender) as u64, completion)
    }
    receiver.await
}

extern "C" fn completion(string: SRString, context: u64) {
    let unbox = unsafe {Box::from_raw(context as *mut Sender<String>)};
    unbox.send(string.to_string());
}

which seems to cause no issues other than the fact that fooExported is obviously not in scope... my issue with it further is that it has a weird looking function signature that I am unfamiliar with.

I have tried the following functions:

swift!(fn fooExported(arg: i64, context: u64, completion: extern "C" fn(SRString, u64)));
swift!(fn fooExported(arg: i64, context: u64, completion: fn(SRString, u64)));
unsafe fn fooExported(arg:i64,context:u64,completion:extern "C" fn(SRString,u64)){
    extern "C" {
        fn fooExported(arg: <i64 as swift_rs::SwiftArg>::ArgType,context: <u64 as swift_rs::SwiftArg>::ArgType,completion: <extern "C" fn(SRString,u64)as swift_rs::SwiftArg>::ArgType);

        }let res = {
        let arg = swift_rs::SwiftArg::as_arg(&arg);
        let context = swift_rs::SwiftArg::as_arg(&context);
        let completion = swift_rs::SwiftArg::as_arg(&completion);
        fooExported(arg,context,completion)
    };
    swift_rs::SwiftRet::retain(&res);
    res
}
unsafe fn fooExported(arg: i64, context: u64, completion: fn(SRString, u64)) {
    unsafe extern "C" {
        fn fooExported(
            arg: <i64 as swift_rs::SwiftArg>::ArgType,
            context: <u64 as swift_rs::SwiftArg>::ArgType,
            completion: <fn(SRString, u64) as swift_rs::SwiftArg>::ArgType,
        );

    }
    let res = {
        let arg = swift_rs::SwiftArg::as_arg(&arg);
        let context = swift_rs::SwiftArg::as_arg(&context);
        let completion = swift_rs::SwiftArg::as_arg(&completion);
        fooExported(arg, context, completion)
    };
    swift_rs::SwiftRet::retain(&res);
    res
}

Englightenment

Okay, reading through the inlined macros (last two examples) I figured that the issue is here: completion: <fn(SRString, u64) as swift_rs::SwiftArg>::ArgType, -- trying to cast a fn into a swift type ?

The aforementioned example on the github issue got it to work, I just dont know how

The times I did get something to run by just removing the type conversion it crashed with the following error:

Failed to look up symbolic reference at 0x1048e194d - offset 288547 - symbol symbolic _____Sg ScP in /target/debug/app
zsh: abort      cargo run```

(reason i tagged it with swift as well is because i copy pasted the swift code, maybe there is a better way to approach this?)
发布评论

评论列表(0)

  1. 暂无评论