【问题标题】:How to pass argument in Swift to C function that takes an UnsafePointer?如何将 Swift 中的参数传递给采用 UnsafePointer 的 C 函数?
【发布时间】:2020-02-27 17:03:57
【问题描述】:

我导入了一个名为 geoToH3 的 C 函数,它返回一个 H3Index(它只是一个 UInt64)。

let h3Index = geoToH3(g: UnsafePointer<GeoCoord>!, r: Int32)

该函数接受一个Int32 和一个GeoCoord 对象,这只是一个带有一对Double 的对象。

let geoCoord = GeoCoord(lat: 45.0, lon: -90.0)

我如何将geoCoord 参数传递给这个函数,因为它需要一个UnsafePointer

【问题讨论】:

  • @MartinR withUnsafePointer 泛型函数将返回 GeoCoord 的类型,据我了解它是如何工作的,但 C 函数需要 UnsafePointer&lt;GeoCoord&gt; 类型的参数。或者它可以返回一个不安全的指针吗?
  • 应该是let h3Index = withUnsafePointer(to: geoCoord) { geoToH3($0, 5) },类似于stackoverflow.com/a/60352083/1187415
  • 您可以将此作为答案,因为这完美地回答了我的问题,谢谢!

标签: swift interop unsafe-pointers


【解决方案1】:

这里必须使用withUnsafePointer(to:)

let h3Index = withUnsafePointer(to: geoCoord) {
     (pointer: UnsafePointer<GeoCoord>) -> H3Index in
     return geoToH3($0, 5)
}

或更短(使用速记参数语法和隐式返回):

let h3Index = withUnsafePointer(to: geoCoord) { geoToH3($0, 5) }
  • withUnsafePointer(to:) 使用指向 geoCoord 值。
  • 以该指针作为第一个参数调用 C 函数。
  • C 函数的返回值是withUnsafePointer(to:) 的返回值并赋值给h3Index

重要的是,指针只在withUnsafePointer(to:)执行期间有效,不得存储或返回以供以后使用。

例如,以下是未定义的行为:

let pointer = withUnsafePointer(to: geoCoord) { return $0 }
let h3Index = geoToH3(pointer, 5)

【讨论】:

  • 我还有一个,刚贴出来,希望你看看……你是神。
【解决方案2】:

只需简单地调用一个包含 UnsafePointer 名称的学生 ref。

let stu = student(id: 1, name: input?.cString(using: .utf8), percentage: 10.0)
passByStudent(stu)

试试这个例子:

MyC.c

#include <stdio.h>

void changeInput(int *output) {
    *output = 5;
}

typedef struct student Student ;

void passByStudent(Student stu);

struct student {
    int id;
    const char *name;
    float percentage;
};

void passByStudent(Student stu) {
    stu.id = 5;
}

ViewController.swift

import UIKit

class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()

        var output: CInt = 0
        changeInput(&output)
        print("output: \(output)")


        let input: String? = "strudent name"
        let stu = student(id: 1, name: input?.cString(using: .utf8), percentage: 10.0)
        passByStudent(stu)
    }
}

按照这个例子一步一步来:

  1. 创建 Swift 项目

  2. 创建 MyC.c 文件并编写代码。

  1. 点击您的项目。
  2. 单击构建设置选项卡。
  3. 选择所有标签
  4. 使用 Objective-c 桥接头搜索
  5. 双击此处。
  6. 左键单击 MyC.c 文件后,将其拖放到弹出层内。

  1. 你可以在 Practice-Bridging-Header.h 中定义你的函数

    void changeInput(int *output);

  1. 在 ViewController 中编写代码。

代码:

import UIKit

class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()

        var output: CInt = 0
        changeInput(&output)
        print("output: \(output)")


        let input: String? = "strudent name"
        let stu = student(id: 1, name: input?.cString(using: .utf8), percentage: 10.0)
        passByStudent(stu)
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多