编译C代码并在Linux下将其暴露给Swift

Sai*_*ira 11 c linux swift swift2

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

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

import Car
Run Code Online (Sandbox Code Playgroud)

我试着写module.modulemap里面目录下的文件.c,.h并且Package.swift文件位于:

module Car {
   header "Car.h"
   export *
}
Run Code Online (Sandbox Code Playgroud)

并运行swift build.这个产量误差:

<unknown>:0: error: unexpected 'commands' value (expected map)
<unknown>:0: error: unable to load build file
Run Code Online (Sandbox Code Playgroud)

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

[更新1]

我已经联系了Max(mxcl) - Swift Package Manager的创建者之一,他告诉我要删除modulemap.c并将.h文件直接放在Sources文件夹中.我编译完这个包后,但它不能用作模块.此外,我无法调用文件中的任何已定义函数.h.

Ana*_*i P 15

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

处理此任务的另一种方法是创建桥接头,如@Philip所建议的那样.这是一个简单的例子.让我们考虑以下C代码:

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

/* In car.c */
int getInt() { return 123; }
Run Code Online (Sandbox Code Playgroud)

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

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

首先car.o,从car.c以下位置创建一个目标文件:

gcc -c car.c
Run Code Online (Sandbox Code Playgroud)

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

swiftc -import-objc-header car.h junk.swift car.o -o junk
Run Code Online (Sandbox Code Playgroud)

运行可执行文件给出:

$ ./junk
Hi from swift!
And here is an int from C: 123!
Run Code Online (Sandbox Code Playgroud)

-import-objc-header选项已隐藏.要查看它和一堆其他隐藏选项,请运行:

swiftc -help-hidden 
Run Code Online (Sandbox Code Playgroud)

我从4月12日开始使用Ubuntu 14.04的Swift 3.0开发快照,可以在这里找到: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++编译器编译,但是使用C语言可以调用的函数extern "C".然后可以从Swift中调用这些函数作为任何C函数.例如,请参阅以下答案:我可以将Swift与C++混合使用吗?像Objective - C .mm文件一样


Phi*_*lip 5

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

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

编辑:我在下面添加了一个完整的示例,其中包含6个文件,用于可能有此问题的其他任何人。它基本上与上面的相同,但是直到我把它放在一起之前,我一直没有看到。同样,它对于需要链接静态库的人可能很有用。

将下面的文件内容复制到适当命名的文件make,然后./hello就可以了。作为记录,我仅在swift 2.2-dev版本上运行(用于swift --version检查您的版本)

  • Linux上的`swift`和`swift build`命令都不具有`-import-objc-header`选项(Swift 3.0) (3认同)
  • 抱歉,应该已经阐明:您应该使用“ swiftc”进行编译 (3认同)