编译C代码并在Linux下将其展示给Swift

有没有办法编译原生的C或C ++代码,并暴露给Linux上的Swift? 我可以看到像libdispatch这样的几个苹果库是用纯C编写的,只要导入它们就可以在Swift中访问它们。

为了设置这个例子,假设我有两个文件Car.cCar.h定义了名为Car结构。 有没有办法,我可以通过编写import语句来编译它们并在Swift中使用它们?

 import Car 

我已经尝试在.c.hPackage.swift文件所在的目录中写入module.modulemap文件:

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

并运行swift build 。 这个产量错误:

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

我正在使用Swift版本3.0-dev(2016年3月24日)

[更新1]

我已经联系了Max(mxcl) – Swift Package Manager的创build者之一,他告诉我摆脱modulemap并将.c.h文件直接放在Sources文件夹中。 我做了包编译后,但它不作为模块。 另外,我不能在.h文件中调用任何已定义的函数。

如果从C代码中构建一个库,可以为它创建一个系统模块 ,然后将其导入到Swift中,请参阅此答案: 在Linux上的Swift中使用C库 。

解决此任务的另一种方法是按照@Philip的建议创建桥接标头。 这是一个简单的例子。 我们来考虑下面的C代码:

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

我们将使用car.h作为桥接头。 swift源是(在文件junk.swift ):

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

首先,从car.c创建一个目标文件car.o

 gcc -c car.c 

现在构建一个可执行文件,如下所示:

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

运行可执行文件给出:

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

-import-objc-header选项是隐藏的。 要看到它和一堆其他隐藏的选项,运行:

 swiftc -help-hidden 

我从4月12日开始使用Swift 3.0的Ubuntu 14.04开发快照,可以在这里找到: https : //swift.org/builds/development/ubuntu1404/swift-DEVELOPMENT-SNAPSHOT-2016-04-12-a/swift-DEVELOPMENT-快照2016年4月12日-A-ubuntu14.04.tar.gz

现在,如果你想使用C ++,你将需要创建一个包装器,用C ++源文件编写,并用C ++编译器编译,但是可以使用extern "C"从C调用函数。 这些函数可以作为任何C函数从Swift中调用。 例如,看这个答案: 我可以混合Swift和C ++吗? 像Objective – C .mm文件一样

在swift中使用C函数需要一个包含所有需要的C功能的桥接头。 例如,包含#include“Car.h”的myBridgingHeader.h以及任何你想要的其他C的东西。 我相信目前不支持C ++。

一旦你有桥头,你需要迅速意识到这一点。 Xcode用户在将它添加到项目中时可以免费获得。 在Linux中,编译时使用'-import-objc-header / path / to / header'标志。

编辑:我已经添加了一个完整的例子,由6个文件组成的任何其他人谁可能有这个问题。 它基本上和上面的一样,但我没有看到,直到我已经把它放在一起哈哈。 另外,对于需要链接静态库的人来说也许是有用的。

复制下面的文件内容到适当的命名文件, make ,然后./hello ,这应该工作。 为了记录,我只在swift版本2.2-dev上运行(使用swift --version来检查你的)

  • hello.swift:

     let n: Int32 = 5 print("Hello, Swift World!") print("mult2(\(n,N)) = \(mult2(n,N))") print("CONST1=\(CONST1), CONST2=\(CONST2), CONST3=\(CONST3)") 
  • bridge.h:

     #include "defs.h" #include "mult.h" 
  • defs.h中:

     #define CONST1 1 #define CONST2 2 #define CONST3 3 
  • mult.h:

     #define N 7 int mult2(int,int); 
  • mult.c:

     #include "defs.h" #include "mult.h" int mult2(int a, int b) { return a*b; } 
  • Makefile文件:

     all: hello hello: libmult.a swiftc hello.swift -import-objc-header ./bridge.h -L. -lmult -o hello libmult.a: mult.o ar -rc libmult.a mult.o ranlib libmult.a mult.o: mult.c mult.h defs.h gcc -c mult.c -o mult.o .PHONY: clean clean: rm -f *.o *.a hello