Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Compile C code and expose it to Swift under Linux

Is there a way to compile native C or C++ code and expose it to Swift on Linux? I can see that several Apple libraries like libdispatch are written in pure C and that you can access them in Swift just by importing them.

To set the example let's say that I have two files Car.c and Car.h that define structure named Car. Is there a way that I can compile them and use them in Swift by writing import statement?

import Car

I've tried writing module.modulemap file inside directory where .c, .h and Package.swift files are located:

module Car {
   header "Car.h"
   export *
}

and running swift build. This yield error:

<unknown>:0: error: unexpected 'commands' value (expected map)
<unknown>:0: error: unable to load build file

I'm using Swift version 3.0-dev (March 24 2016)

[Update 1]

I've contacted Max(mxcl) - one of the creators of Swift Package Manager and he told me to get rid of the modulemap and put the .c and .h files directly in Sources folder. After I did that package compiled but it's not available as module. Also I can't call any of the defined functions in the .h file.

like image 927
Said Sikira Avatar asked Apr 12 '16 10:04

Said Sikira


1 Answers

If you build a library out of your C code, you can create a system module for it, which can then be imported into Swift, see this answer: Use a C library in Swift on Linux.

Another way to approach this task is to create a bridging header, as suggested by @Philip. Here is an oversimplified example. Let's consider the following C code:

/* In car.h */
int getInt();

/* In car.c */
int getInt() { return 123; }

We will use car.h as the bridging header. The swift source is (in file junk.swift):

print("Hi from swift!")
var i = getInt()
print("And here is an int from C: \(i)!")

First, create an object file, car.o, from car.c:

gcc -c car.c

Now build an executable, junk, as follows:

swiftc -import-objc-header car.h junk.swift car.o -o junk

Running the executable gives:

$ ./junk
Hi from swift!
And here is an int from C: 123!

The -import-objc-header option is hidden. To see it and a bunch of other hidden options, run:

swiftc -help-hidden 

I did this using Swift 3.0 development snapshot for Ubuntu 14.04 from April 12, available here: https://swift.org/builds/development/ubuntu1404/swift-DEVELOPMENT-SNAPSHOT-2016-04-12-a/swift-DEVELOPMENT-SNAPSHOT-2016-04-12-a-ubuntu14.04.tar.gz

Now, if you want to use C++, you will need to create a wrapper, written in a C++ source file and compiled with a C++ compiler, but with functions callable from C by using extern "C". Those functions can then be called from Swift as any C function. See, for example, this answer: Can I mix Swift with C++? Like the Objective - C .mm files

like image 132
Anatoli P Avatar answered Sep 19 '22 17:09

Anatoli P