Skip to content

Commit cd67584

Browse files
committed
[interop][SwiftToCxx] support NSString -> Swift String bridging in C++
1 parent 83db71b commit cd67584

File tree

3 files changed

+29
-0
lines changed

3 files changed

+29
-0
lines changed

lib/PrintAsClang/PrintClangValueType.cpp

+15
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,10 @@ static void addCppExtensionsToStdlibType(const NominalTypeDecl *typeDecl,
131131
cPrologueOS << "SWIFT_EXTERN void *_Nonnull "
132132
"$sSS10FoundationE19_bridgeToObjectiveCSo8NSStringCyF(swift_interop_stub_"
133133
"Swift_String) SWIFT_NOEXCEPT SWIFT_CALL;\n";
134+
cPrologueOS << "SWIFT_EXTERN swift_interop_stub_Swift_String "
135+
"$sSS10FoundationE36_"
136+
"unconditionallyBridgeFromObjectiveCySSSo8NSStringCSgFZ("
137+
"void * _Nullable) SWIFT_NOEXCEPT SWIFT_CALL;\n";
134138
printer.printObjCBlock([](raw_ostream &os) {
135139
os << " ";
136140
ClangSyntaxPrinter(os).printInlineForThunk();
@@ -139,6 +143,17 @@ static void addCppExtensionsToStdlibType(const NominalTypeDecl *typeDecl,
139143
"*)(_impl::$sSS10FoundationE19_bridgeToObjectiveCSo8NSStringCyF(_impl::swift_interop_"
140144
"passDirect_Swift_String(_getOpaquePointer())));\n";
141145
os << " }\n";
146+
os << "static ";
147+
ClangSyntaxPrinter(os).printInlineForThunk();
148+
os << "String init(NSString * _Nonnull nsString) noexcept {\n";
149+
os << " auto result = _make();\n";
150+
os << " auto res = "
151+
"_impl::$sSS10FoundationE36_"
152+
"unconditionallyBridgeFromObjectiveCySSSo8NSStringCSgFZ((__bridge "
153+
"void *)nsString);\n";
154+
os << " memcpy(result._getOpaquePointer(), &res, sizeof(res));\n";
155+
os << " return result;\n";
156+
os << " }\n";
142157
});
143158
} else if (typeDecl == typeDecl->getASTContext().getOptionalDecl()) {
144159
// Add additional methods for the `Optional` declaration.

test/Interop/SwiftToCxx/stdlib/string/string-to-nsstring.mm

+8
Original file line numberDiff line numberDiff line change
@@ -61,5 +61,13 @@ int main() {
6161
assert(std::string(nsStr.UTF8String) == "hello");
6262
assert([nsStr isEqualToString:@"hello"]);
6363
}
64+
65+
{
66+
NSString *nsStr = @"nsstr";
67+
auto str = String::init(nsStr);
68+
NSString *nsStr2 = str;
69+
assert(std::string(nsStr.UTF8String) == "nsstr");
70+
assert([nsStr2 isEqualToString:nsStr]);
71+
}
6472
return 0;
6573
}

test/Interop/SwiftToCxx/stdlib/swift-stdlib-in-cxx.swift

+6
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,12 @@
7979
// CHECK-NEXT: inline __attribute__((always_inline)) operator NSString * _Nonnull () const noexcept {
8080
// CHECK-NEXT: return (__bridge_transfer NSString *)(_impl::$sSS10FoundationE19_bridgeToObjectiveCSo8NSStringCyF(_impl::swift_interop_passDirect_Swift_String(_getOpaquePointer())));
8181
// CHECK-NEXT: }
82+
// CHECK-NEXT: static inline __attribute__((always_inline)) String init(NSString * _Nonnull nsString) noexcept {
83+
// CHECK-NEXT: auto result = _make();
84+
// CHECK-NEXT: auto res = _impl::$sSS10FoundationE36_unconditionallyBridgeFromObjectiveCySSSo8NSStringCSgFZ((__bridge void *)nsString);
85+
// CHECK-NEXT: memcpy(result._getOpaquePointer(), &res, sizeof(res));
86+
// CHECK-NEXT: return result;
87+
// CHECK-NEXT: }
8288
// CHECK-EMPTY:
8389
// CHECK-NEXT: #endif
8490
// CHECK-NEXT: private:

0 commit comments

Comments
 (0)