Get pointer to C char array in Swift

A have the following structure (defined in bson.h of the mongodb c driver):

typedef struct { uint32_t domain; uint32_t code; char message[504]; } bson_error_t; 

In Swift, I have a pointer to this structure as follows:

 err: UnsafePointer<bson_error_t> = ... 

Now I cannot convert message[504] (which Swift sees as a tuple (Int8, Int8, Int8, ... 504 times)) to char* to use it in String.fromCString (). Is it possible to do this in Swift? As a workaround, I created a helper function C in a separate .c file that accepts err *bson_error_t and returns char* , but this is strange if Swift cannot do it on its own.

+5
source share
3 answers

Here's my suggestion (similar to the rintaro approach, maybe a little simpler):

 var err: UnsafeMutablePointer<bson_error_t> = ... var msg = err.memory.message let msgString = withUnsafePointer(&msg) { String.fromCString(UnsafePointer($0)) } println(msgString) 
+1
source

It is not beautiful, not intuitive, but it is doable. Purely in Swift, no glue C code required. Minimal demo:

bh

 typedef struct { int n; char s[8]; } Bridged; Bridged *make_b(void); 

bc

 #include <stdlib.h> #include <string.h> #include "bh" Bridged *make_b(void) { Bridged *p = calloc(sizeof(*p), 1); memcpy(p->s, "foobarz", 8); return p; } 

b.swift:

 // half compile-time, half run-time black magic func toCharArray<T>(t: T) -> [CChar] { var a: [CChar] = [] let mirror = reflect(t) for i in 0 ..< mirror.count { a.append(mirror[i].1.value as CChar) } return a } let b = make_b().memory.s // bridged tuple of 8 chars let a = toCharArray(b) // Swift array of (8) CChars let s = String.fromCString(a) // proper Swift string println(s) 

Compile:

 $ xcrun swiftc -O -c b.swift -import-objc-header bh $ clang -O2 -c bc -o bco $ xcrun swiftc bo bco -ob 

Run:

 $ ./b Optional("foobarz") 
+3
source

Quick hack to extract String message from bson_error_t :

 extension bson_error_t { mutating func messageString() -> String? { return String.fromCString( { (p:UnsafePointer<Void>) in UnsafePointer<CChar>(p) }(&self.message.0) ) } } // Usage: var err: UnsafeMutablePointer<bson_error_t> = ... ... let errMessage = err.memory.messageString() 
0
source

Source: https://habr.com/ru/post/1206070/


All Articles