有没有办法编译原生的C或C ++代码,并暴露给Linux上的Swift? 我可以看到像libdispatch这样的几个苹果库是用纯C编写的,只要导入它们就可以在Swift中访问它们。
为了设置这个例子,假设我有两个文件Car.c
和Car.h
定义了名为Car
结构。 有没有办法,我可以通过编写import语句来编译它们并在Swift中使用它们?
import Car
我已经尝试在.c
, .h
和Package.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