lurning too koad
lurning too koad

Reputation: 2974

How to pass argument in Swift to C function that takes an UnsafePointer?

I've imported a C function called geoToH3 that returns an H3Index (which is just a UInt64).

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

The function takes an Int32 and a GeoCoord object, which is just an object with a pair of Double.

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

How do I pass the geoCoord argument to this function since it takes an UnsafePointer?

Upvotes: 0

Views: 873

Answers (2)

AMIT
AMIT

Reputation: 924

Just simply call with a student ref there contain UnsafePointer name.

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

Try this example:

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)
    }
}

Follow this example step-by-step:

  1. Create a Swift Project

  2. Create MyC.c file and write code.

enter image description here

  1. Click on your project.
  2. Click the Build Setting Tab.
  3. Select all tab
  4. search with Objective-c Bridging Header
  5. Double click Here.
  6. After that left-click on MyC.c file, drag and drop inside popup layer.

enter image description here

  1. You can define your function inside Practice-Bridging-Header.h

    void changeInput(int *output);

enter image description here

  1. Write code inside your ViewController.

Code:

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)
    }
}

Upvotes: 1

Martin R
Martin R

Reputation: 540105

withUnsafePointer(to:) must be used here:

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

or shorter (using shorthand parameter syntax and implicit return):

let h3Index = withUnsafePointer(to: geoCoord) { geoToH3($0, 5) }
  • withUnsafePointer(to:) calls the closure with a pointer to the geoCoord value.
  • The C function is called with that pointer as the first argument.
  • The return value from the C function is the return value of withUnsafePointer(to:) and assigned to h3Index.

It is important that the pointer is only valid during the execution of withUnsafePointer(to:) and must not be stored or returned for later use.

As an example, the following would be undefined behaviour:

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

Upvotes: 1

Related Questions