如何在Rust中调用Swift函数?

XAM*_*cky 5 objective-c ffi rust swift

我有一个用Swift编写的函数,我想从Rust调用。我尝试通过Objective-C公开它,但是由于ld说它找不到而继续出错_foo。通过将Rust项目编译为staticlib,Rust项目链接到Swift项目。

foo.h

#pragma once

#include <stdint.h>

uint8_t foo_bridge(uint8_t);
Run Code Online (Sandbox Code Playgroud)

foo.m

#import <Foundation/Foundation.h>
#import <Foo-Swift.h>

uint8_t foo_bridge(uint8_t byte) {
    return foo(byte);
}
Run Code Online (Sandbox Code Playgroud)

斯威夫特

public func foo(byte: UInt8) -> UInt8 {
    return byte * 2
}
Run Code Online (Sandbox Code Playgroud)

src / lib.rs

public func foo(byte: UInt8) -> UInt8 {
    return byte * 2
}
Run Code Online (Sandbox Code Playgroud)

Bar-Bridging-Header.h

extern "C" {
    pub fn foo_bridge(byte: u8) -> u8;
}
Run Code Online (Sandbox Code Playgroud)

货代

[package]
name = "foo"
version = "0.1.0"

[lib]
name = "foo"
crate-type = ["staticlib"]
Run Code Online (Sandbox Code Playgroud)

小智 7

这里的问题是试图从Objective-C调用裸Swift函数,不支持。

如果您检查Foo-Swift.h标题,则会发现该foo()函数不存在,这表明该函数的符号_foo在运行时也将不可用。

解决方案是将foo()函数放在可以从Objective-C调用的东西中,例如从NSObject派生的类:

class Foo: NSObject {
    class func foo(byte: UInt8) -> UInt8 {
        return byte * 2
    }
}
Run Code Online (Sandbox Code Playgroud)

完成后,您会发现Foo-Swift.h标题现在具有一个接口:

@interface Foo : NSObject
+ (uint8_t)fooWithByte:(uint8_t)byte;
- (nonnull instancetype)init OBJC_DESIGNATED_INITIALIZER;
@end
Run Code Online (Sandbox Code Playgroud)

既然我们知道它现在可以从Objective-C中获得,我们可以这样称呼它:

uint8_t foo_bridge(uint8_t byte) {
    return [Foo fooWithByte:byte];
}
Run Code Online (Sandbox Code Playgroud)