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?