![](/img/trans.png)
[英]How can I compile ANSI C99-based MEX code delivered with Linux makefiles under Win64 MATLAB?
[英]Compile C code and expose it to Swift under Linux
有没有办法编译本机 C 或 C++ 代码并将其公开给 Linux 上的 Swift? 我可以看到像libdispatch这样的几个 Apple 库是用纯 C 编写的,您只需导入它们就可以在 Swift 中访问它们。
举个例子,假设我有两个文件Car.c
和Car.h
,它们定义了名为Car
结构。 有没有办法通过编写导入语句来编译它们并在 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 的创建者之一,他告诉我摆脱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.