Try mixing C and Swift in one project (OS X, Linux)

Overview

wrap up

  1. Create an object file from a C language source with clang
  2. Compile Swift source with object files with swiftc
  3. That's it (you don't need to read this article if you understand this)

environment

OS X


$ clang --version
Apple LLVM version 7.3.0 (clang-703.0.29)
Target: x86_64-apple-darwin15.5.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin

$ swift --version
Apple Swift version 2.2 (swiftlang-703.0.18.1 clang-703.0.29)
Target: x86_64-apple-macosx10.9

Linux


$ clang --version
clang version 3.8.0 (tags/RELEASE_380/final)
Target: x86_64-unknown-linux-gnu
Thread model: posix
InstalledDir: /usr/local/bin

$ swift --version
Swift version 2.2.1 (swift-2.2.1-RELEASE)
Target: x86_64-unknown-linux-gnu

source file

For the sake of simplicity, I have prepared only three files this time.

$ ls
c.c  c.h  swift.swift

c.h


#include <stdio.h>
void c_function(const char * string);

c.c


#include "c.h"
void c_function(const char * string) {
  (void)printf("%s", string);
}

swift.swift


c_function("Hello, I'm Swift.\n")

Compilation procedure

Create object file from C source

OS&#x0020;X,&#x0020;Linux common


$ clang -c c.c -oc.o
$ ls
c.c  c.h  c.o  swift.swift

did it. You can use gcc instead of clang.

Compile Swift source with object files

OS&#x0020;X


$ xcrun --sdk macosx swiftc swift.swift c.o -import-objc-header c.h
ld: warning: object file (c.o) was built for newer OSX version (10.11) than being linked (10.9)
$ ls
c.c		c.h		c.o		main		swift.swift
$ ./main
Hello, I'm Swift.

Linux


$ swiftc swift.swift c.o -import-objc-header c.h
$ ls
c.c  c.h  c.o  main  swift.swift
$ ./main
Hello, I'm Swift.

did it. This is the end. It ’s easy, is n’t it? [^ 1]

[^ 1]: There is a warning on OS X, but it's virtually harmless. Looking at the target of Swift 2.2 on OS X, it is x86_64-apple-macosx10.9, so it may be better to compile c.o using the SDK of 10.9 ... but ignore it here.

Bloopers

-import-objc-header?

What is it delicious?

For some reason I don't see this option even with swiftc --help [^ 2].

[^ 2]: I enjoy "[Swift without Xcode (from REPL to library generation) # Objective-C and C bridging](http://qiita.com/demmy/items/c4a6a430787d3097a6df#objective-c and I learned from "Bridge c)".

Without -import-objc-header?

$ swiftc swift.swift c.o
swift.swift:1:1: error: use of unresolved identifier 'c_function'
c_function("Hello, I'm Swift.\n")
^~~~~~~~~~

... isn't it?

Not -import-c-header.

Since it is a C language header, I want to use -import-c-header ...

$ swiftc swift.swift c.o -import-c-header c.h
<unknown>:0: error: unknown argument: '-import-c-header'

…I got scolded. Objective-C completely embraces C language in terms of language specifications, so it seems theoretically that there is no problem reading the C header with -import-objc-header, but ... it seems unpleasant.

Should I use xcrun on OS X?

OS&#x0020;X


$ swiftc swift.swift c.o -import-objc-header c.h
(Abbreviation)./c.h:1:10: error: 'stdio.h' file not found
#include <stdio.h>
         ^
<unknown>:0: error: failed to import bridging header 'c.h'

The header of the C language standard library cannot be found. There is no problem with Linux.

A little more roundabout way

After creating the object file from the C language source, create the object file in Swift and then try to put it together. In other words ...

OS&#x0020;X,&#x0020;Linux common


$ clang -c c.c -oc.o
$ ls
c.c  c.h  c.o  swift.swift

This is the same. Next, create an object file in Swift as well:

OS&#x0020;X


$ xcrun --sdk macosx swiftc -c swift.swift -oswift.o -import-objc-header c.h
$ ls
c.c		c.h		c.o		swift.o		swift.swift

Linux


$ swiftc -c swift.swift -oswift.o -import-objc-header c.h
$ ls
c.c  c.h  c.o  swift.o  swift.swift

Summarize the c.o and swift.o created in this way:

OS&#x0020;X,&#x0020;Linux common


$ swiftc swift.o c.o 2> /dev/null
$ ls
c.c  c.h  c.o  main  swift.o  swift.swift
$ ./main
Hello, I'm Swift.

did it. By the way, if you do clang swift.o c.o -omain, you will be told where libswiftCore. {Dylib, so} is (I got a very confusing error message on Linux). So, for OS X, compile (link) with clang swift.o co -omain -L / Applications / Xcode.app / Contents / Developer / Toolchains / XcodeDefault.xctoolchain / usr / lib / swift / macosx -lswiftCore I can, but when I try to do it

OS&#x0020;X


$ ./main
dyld: Library not loaded: @rpath/libswiftCore.dylib
  Referenced from: (Abbreviation)./main
  Reason: image not found
Trace/BPT trap: 5

Is said. … Use swiftc obediently.

Recommended Posts

Try mixing C and Swift in one project (OS X, Linux)
Try mixing more C and Swift in one project (OS X, Linux)
Organize builds in C ++ / Java and Win / Linux combinations
Try gRPC in Spring Boot & Spring Cloud project (Mac OS)
Try running ruby-net-nntp and tmail in 2020
CGI in C and Dart: Introduction (1)
Handle C char ** well in Swift