如何在Rust中调用Swift函数?

时间:2017-03-20 12:00:05

标签: objective-c swift rust ffi

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

foo.h中

#pragma once

#include <stdint.h>

uint8_t foo_bridge(uint8_t);

foo.m

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

uint8_t foo_bridge(uint8_t byte) {
    return foo(byte);
}

bar.swift

public func foo(byte: UInt8) -> UInt8 {
    return byte * 2
}

的src / lib.rs

extern "C" {
    pub fn foo_bridge(byte: u8) -> u8;
}

酒吧-桥接-Header.h

#import "foo.h"

Cargo.toml

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

[lib]
name = "foo"
crate-type = ["staticlib"]

1 个答案:

答案 0 :(得分:4)

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

如果您检查Foo-Swift.h标题,则会发现foo()功能不存在,这表示其符号_foo赢了&# 39;在运行时也可以使用。

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

class Foo: NSObject {
    class func foo(byte: UInt8) -> UInt8 {
        return byte * 2
    }
}

一旦你这样做,你会发现Foo-Swift.h标题现在有一个界面:

@interface Foo : NSObject
+ (uint8_t)fooWithByte:(uint8_t)byte;
- (nonnull instancetype)init OBJC_DESIGNATED_INITIALIZER;
@end

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

uint8_t foo_bridge(uint8_t byte) {
    return [Foo fooWithByte:byte];
}