Using imported C functions in Swift

50 Views Asked by At

I am trying to use a C function from Swift. The program just do a DNS lookup. After creating the bridge-header the program works ok and prints:

IP address of www.google.com is 142.250.187.196

but I suspect that the conversion of types from C to Swift can be simplified. I don't have any experience with C interoperability.

The Swift program is:

import SwiftUI

struct ContentView: View {
    @State private var  dnsLookup = ""
    var body: some View {
       
        VStack {
           
            Text(dnsLookup)
        }
        .padding()
        .task{
           testFunc()
            let hostname:NSString = "www.google.com"
            // Convert the Swift strings to CChars (or Int8) that map to
            
            let c_hostname = UnsafeMutablePointer<Int8>(mutating:hostname.utf8String)
            if let ipAddress = getHostAddress(c_hostname) {
                dnsLookup = "IP address of \(hostname): \(String(cString: ipAddress))"
            } else {
                dnsLookup  = "Failed to retrieve IP address for \(hostname)"
            }
            
        }
    }
    

    
}

#Preview {
    ContentView()
}

The C function is:

#include "GetHostAddress.h"

#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <netinet/in.h>

#define MAX_IP_LENGTH INET_ADDRSTRLEN

char* getHostAddress(const char* hostname) {
    printf ("Host: %s\n", hostname);
    int status;
    struct addrinfo hints, *res, *p;
    char ipstr[MAX_IP_LENGTH];

    memset(&hints, 0, sizeof hints);
    hints.ai_family = AF_INET; // IPv4
    hints.ai_socktype = SOCK_STREAM;

    if ((status = getaddrinfo(hostname , NULL, &hints, &res)) != 0) {
            fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(status));
            return NULL;
        }

    for (p = res; p != NULL; p = p->ai_next) {
        struct sockaddr_in *ipv4 = (struct sockaddr_in *)p->ai_addr;
        void *addr = &(ipv4->sin_addr);
        inet_ntop(p->ai_family, addr, ipstr, sizeof ipstr);
    }

    freeaddrinfo(res);
    return strdup(ipstr);
}

It is just a function that returns the IP of an url ("www.google.com" hardcoded con the Swift program to simplify)

The signature of the C function is:

char* getHostAddress(const char* hostname);

According to Apple documentation the Swift equivalent would be:

 getHostAddres(UnsafePointer<Int32> hostname) -> UnsafeMutablePointer<Int32>

So for the parameter ("www.google.com") first is converted to NSString and then we applied .utf8 that returns a null-terminated UTF8 representation.

For the return type we can use:

String(cString: ipAddress))

This two conversions are correct or can be simplified?

0

There are 0 best solutions below