RussBaz
(Russ)
October 11, 2024, 6:01am
1
Hi. I can easily import C code into my Swift code and compile it with something like this (from basic.c into main.swift):
swiftc main.swift basic.c -import-objc-header basic.h
However, I can not figure out how to do the opposite. How do I import a function defined in main.swift into the basic.c?
Thank you.
1 Like
Cyberbeni
(Benedek Kozma)
October 11, 2024, 6:25am
2
RussBaz
(Russ)
October 11, 2024, 6:59am
3
Thanks. While it works, it also breaks in some other ways (which is confusing). It can no longer find a function declared in C.
Let's say I have the following 3 files:
// basic.c
#include "basic.h"
#include "main.h"
void hello() {
printf("Hello, C!\n");
doSomething();
}
// basic.h
#ifndef basic_h
#define basic_h
#include <stdio.h>
void hello();
#endif /* basic_h */
// main.swift
@_cdecl("doSomething")
public func doSomething() {
print("something")
}
print("Hello, Swift!")
hello()
What will be the right combination of commands to build main
executable (main.swift is an entry point, of course)?
1 Like
ole
(Ole Begemann)
October 11, 2024, 2:26pm
4
If you rename basic.c
to basic.m
, making this a mixed Swift-ObjC target, this works for me on macOS 15.0 with Xcode 16.0 (Swift 6.0):
$ swiftc -import-objc-header basic.h \
-emit-clang-header-path main.h \
main.swift basic.m
$ ./main
Hello, Swift!
Hello, C!
something
Sorry if this doesn't help you, but I found it interesting.
1 Like
RussBaz
(Russ)
October 11, 2024, 2:46pm
5
You know what? I just tried that, and it worked like a charm!!!! Thanks. But it refuses to work with .c
extension…
What is going on!? I am so confused.
1 Like
ole
(Ole Begemann)
October 11, 2024, 4:20pm
6
I don't know.
This recent post seems relevant: Is there a way to list the APIs provided by my dynamic library? . It seems to suggest that the emitted header contains Obj-C-specific features. (The OP speaks of -emit-objc-header-path
, not -emit-clang-header-path
, but in my testing both flags emit the same C header, at least when C++ interop is not enabled. I haven't tried it with C++ interop.)
RussBaz
(Russ)
October 11, 2024, 6:31pm
7
Another fun fact. I have added -cxx-interoperability-mode=default
flag, left basic.c
and main.swift
files as is and updated my basic.h
to:
#ifndef basic_h
#define basic_h
#ifdef __cplusplus
extern "C" {
#endif
#include <stdio.h>
void hello();
#ifdef __cplusplus
}
#endif
#endif
and it worked!
Here is my current command:
swiftc -import-objc-header basic.h -emit-clang-header-path main.h main.swift basic.c -cxx-interoperability-mode=default
3 Likes