Вызов Rust из Swift

На стороне Rust я написал функцию, которая возвращает String как указатель байтов (размещенный в памяти как C-структура):

#[repr(C)]
pub struct RustByteSlice {
    pub bytes: *const u8,
    pub len: size_t,
}

#[no_mangle]
pub extern "C" fn get_string_from_rust() -> RustByteSlice {
    let s = "This is a string from Rust.";
    RustByteSlice {
        bytes: s.as_ptr(),
        len: s.len() as size_t,
    }
}

При создании для него файла заголовка с помощью cbindgen он дает мне следующий результат:

#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>

typedef struct {
  const uint8_t *bytes;
  size_t len;
} RustByteSlice;

RustByteSlice get_string_from_rust(void);

char *hello(const char *to);

void hello_release(char *s);

void utf8_bytes_to_rust(const uint8_t *bytes, size_t len);

В моем проекте Xcode этот заголовок используется в качестве связующего заголовка, а общая библиотека, скомпилированная из кода ржавчины, добавляется в список зависимостей. Папки заголовка и включения определяются в свойствах сборки.

На быстрой стороне я вызываю функцию ржавчины следующим образом:

struct RustByteSlice {
    var bytes: UnsafePointer<UInt8>
    var len: Int

    func asUnsafeBufferPointer() -> UnsafeBufferPointer<UInt8> {
        return UnsafeBufferPointer(start: bytes, count: len)
    }
    func asString(encoding: String.Encoding = String.Encoding.utf8) -> String? {
        return String(bytes: asUnsafeBufferPointer(), encoding: encoding)
    }
}

func strPtrRet() {
    let rustString: RustByteSlice = get_string_from_rust()

    if let stringFromRust = rustString.asString() {
        print("got a string from Rust: (stringFromRust)")
    } else {
        print("Could not parse Rust string as UTF-8")
    }
}

В строке let rustString: RustByteSlice = get_string_from_rust() я получаю следующую ошибку:

Cannot convert value of type '__ObjC.RustByteSlice' to specified type 'ed25_ios_app.RustByteSlice'

Как я могу решить эту ошибку или обойти ее?


person Nicolas Marshall    schedule 20.03.2020    source источник
comment
Мне кажется, что вы переопределяете тип RustByteSlice в Swift вместо того, чтобы просто использовать импортированный тип.   -  person NebulaFox    schedule 21.03.2020


Ответы (1)


После проработки кода вы переопределяете RustByteSlice.

Из Использование импортированных структур C и объединений в Swift вам не нужно чтобы переопределить его, поскольку он автоматически импортирует структуру.

Приведенный ниже быстрый код работает.

func strPtrRet() -> String? {
    let rustString: RustByteSlice = get_string_from_rust()
    let buffer = UnsafeBufferPointer(start: rustString.bytes, count: rustString.len)
    let string = String(bytes: buffer, encoding: String.Encoding.utf8)

    if let stringFromRust = string {
        print("got a string from Rust: (stringFromRust)")
    } else {
        print("Could not parse Rust string as UTF-8")
    }

    return string
}

person NebulaFox    schedule 21.03.2020
comment
Отлично, большое спасибо! И спасибо, что указали мне на нужные документы - person Nicolas Marshall; 21.03.2020