我想用 C++ 编写一个模块,并用 C 编写一些可在 Swift 中访问的函数。
我有点困惑,因为无论我做什么,SPM 都坚持尝试编译 C++ 代码,就好像它是 Objective-C 一样,当然它找不到正确的头文件。
这是我的尝试。
源码目录结构:
Sources
|
+-CxxModule
| |
| +-include
| | |
| | +-CxxModule.hpp
| |
| +-CxxModule.cpp
|
+-SwiftModule
|
+-SwiftModule.swift
清单 Package.swift
如下:
// swift-tools-version: 5.6
import PackageDescription
let package = Package(
name: "CxxLibrary",
products: [
.library(
name: "CxxLibrary",
targets: ["SwiftModule"]),
],
dependencies: [
],
targets: [
.target(
name: "CxxModule",
dependencies: []),
.target(
name: "SwiftModule",
dependencies: ["CxxModule"],
path: "Sources/SwiftModule"
),
]
)
CxxModule.hpp
如下:
#ifndef CxxModule_hpp
#define CxxModule_hpp
#include <iostream>
extern "C" void printHello();
#endif /* CxxModule_hpp */
CxxModule.cpp
如下:
#include "CxxModule.hpp"
void printHello() {
// use something from the standard library to make sure
// c++ is really being used
std::cout << "Hello, world!" << std::endl;
}
最后,SwiftModule.swift
:
import CxxModule
我错过了什么?有没有办法告诉 SPM 该模块应该在 C++ 中?还是目前根本不受支持?
注意:如果我消除 Swift 目标,C++ 编译得很好。
回答1
我能够解决这个问题。答案是“是”,只要暴露于 Swift 的标头在纯 C 中是可读的。
首先,我将所有 C++ 特定代码(尤其是引用标准库的头文件)移动到源 cpp
文件中:
#include <iostream>
#include "CxxModule.hpp"
void printHello() {
// use something from the standard library to make sure
// c++ is really being used
std::cout << "Hello, world!" << std::endl;
}
其次,我添加了宏以使标头在 C 和 C++ 中都可读:
#ifndef CxxModule_hpp
#define CxxModule_hpp
#ifdef __cplusplus
extern "C" {
#endif
void printHello();
#ifdef __cplusplus
}
#endif
#endif /* CxxModule_hpp */
文件结构和 Swift 模块保持不变。
教训:任何将被 C++ 和 Swift 读取的标头都必须被两者读取。 (Swift 能够理解 C 头文件,但不能理解 C++ 头文件,至少在当前状态下是这样。)