有没有办法编译本机C或C ++代码并将其暴露给Linux上的Swift?我可以看到像libdispatch这样的几个Apple库是用纯C编写的,只要导入它们就可以在Swift中访问它们。
要设置示例,我们假设我有两个文件Car.c
和Car.h
来定义名为Car
的结构。有没有办法可以编译它们并通过编写import语句在Swift中使用它们?
import Car
我尝试在module.modulemap
,.c
和.h
文件所在的目录中编写Package.swift
个文件:
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的创建者之一,他告诉我要删除modulemap
并放置.c
和.h
个文件直接在Sources
文件夹中。我编译完这个包后,但它不能用作模块。此外,我无法调用.h
文件中的任何已定义函数。
答案 0 :(得分:13)
如果您使用C代码构建库,则可以为其创建系统模块,然后可以将其导入Swift,请参阅以下答案:Use a C library in Swift on Linux。
另一种处理此任务的方法是创建一个桥接标头,如@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.o
:
car.c
gcc -c car.c
现在构建一个可执行文件junk
,如下所示:
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-SNAPSHOT-2016-04-12-a-ubuntu14.04.tar.gz
现在,如果你想使用C ++,你需要创建一个包装器,用C ++源文件编写并用C ++编译器编译,但使用extern "C"
从C调用的函数。然后可以从Swift中调用这些函数作为任何C函数。例如,请参阅此答案:Can I mix Swift with C++? Like the Objective - C .mm files
答案 1 :(得分:4)
在swift中使用C函数需要一个桥接头,其中包含您需要的所有C功能。例如,myBridgingHeader.h包含#include&#34; Car.h&#34;以及您想要的任何其他C内容。我相信目前不支持C ++。
一旦你有了桥接头,你需要迅速了解它。 Xcode用户在将其添加到项目中时可以免费获得。在Linux中,使用&#39; -import-objc-header / path / to / header&#39;编译时标记。
编辑:我已经在下面添加了一个完整的示例,其中包含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;
}
生成文件:
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