繁体   English   中英

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

[英]Compile C code and expose it to Swift under Linux

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

举个例子,假设我有两个文件Car.cCar.h ,它们定义了名为Car结构。 有没有办法通过编写导入语句来编译它们并在 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 的创建者之一,他告诉我摆脱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 作为桥接头。 快速来源是(在文件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 日开始使用 Ubuntu 14.04 的 Swift 3.0 开发快照,可在此处获取: 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 调用函数。 然后可以像任何 C 函数一样从 Swift 调用这些函数。 例如,请参阅此答案: 我可以将 Swift 与 C++ 混合使用吗? 像 Objective-C .mm 文件

在 swift 中使用 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检查你的)

  • 你好.swift:

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

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

     #define CONST1 1 #define CONST2 2 #define CONST3 3
  • 多小时:

     #define N 7 int mult2(int,int);
  • 多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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM