For debug reasons, I wanted to print the dns servers used in my iPhone. A quick hacky way is to print the contents of /etc/resolv.conf. This works for the simulator, actually revealing the contents of MacOS resolv.conf but not for an actual iPhone device, those files there are protected and restricted by Apple (need to jailbreak it).

After some browsing, I found a snippet in stackoverflow:

How do we run c code in a modern iPhone app though? Turns out to be kinda simple nowadays.

TLDR; check my example swiftUI project on github:

  1. We create a c file from Xcode and paste the code inside a function.
  2. We create a header file, which needs to expose the signature of the function we wrote. This header file needs the following directives:
#ifndef Dns_h
#define Dns_h

void ourFunction(void);

  1. The magic happens in the bridging header, where we include the header file, making it exposable to our swift code.

This works for simple c code, eg just some printfs.

The debugging code for the dns server uses some weird c functions which although are recognised by the compiler, cannot be linked in the final product when building. Going to the manual page of res_init (which one of the complaints of the linker), we see:

LIBRARY DNS Resolver Library (libresolv, -lresolv)

which means we have to instuct linker to use this library: from Build settings of our target, add -lresolv to Other linker flags. Voila, now it builds and prints our phone dns server(s).

Bonus: From the c code, the directives available in our swift files do not work unless we “enable” them. You do that by adding each directive in Other c flags (section Build settings->Custom compiler flags): -DTARGET_OS_IPHONE