'Can I mix C++ and Swift in the same swift package, using the Swift Package Manager?
I would like to write one module in C++, and make some functions in C that are accessible in Swift.
I am somewhat baffled, because no matter what I do, the SPM insists on attempting to compile the C++ code as if it were Objective-C, and of course it cannot find the right headers.
Here is my attempt.
Source directory structure:
Sources
|
+-CxxModule
| |
| +-include
| | |
| | +-CxxModule.hpp
| |
| +-CxxModule.cpp
|
+-SwiftModule
|
+-SwiftModule.swift
The manifest Package.swift is as follows:
// 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 is as follows:
#ifndef CxxModule_hpp
#define CxxModule_hpp
#include <iostream>
extern "C" void printHello();
#endif /* CxxModule_hpp */
CxxModule.cpp is as follows:
#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;
}
Finally, SwiftModule.swift:
import CxxModule
What am I missing? Is there a way to tell SPM that the module is supposed to be in C++? Or is this simply unsupported at the moment?
Note: the C++ compiles just fine if I eliminate the Swift target.
Solution 1:[1]
I was able to resolve the problem. The answer is “Yes” so long as the header exposed to Swift is readable in pure C.
First, I moved all C++-specific code (especially headers referencing the standard library) into the source cpp file:
#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;
}
Second, I added macros to make the header readable in both C and C++:
#ifndef CxxModule_hpp
#define CxxModule_hpp
#ifdef __cplusplus
extern "C" {
#endif
void printHello();
#ifdef __cplusplus
}
#endif
#endif /* CxxModule_hpp */
The file structure and Swift module remain unchanged.
The lesson: any header that is going to be read by both C++ and Swift must be readable by both. (Swift is able to understand C headers, but not C++ headers, at least in its present state.)
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | AthanasiusOfAlex |
