Obtain a pointer to a C char array in Swift

只谈情不闲聊 提交于 2019-11-30 21:37:32

Here my suggestion (similar to rintaro's approach, perhaps slightly simpler):

var err: UnsafeMutablePointer<bson_error_t> = ...

var msg = err.memory.message
let msgString = withUnsafePointer(&msg) { String.fromCString(UnsafePointer($0)) }
println(msgString)

It's not pretty, not intuitive, but it's doable. Purely in Swift, no C glue code needed. A minimal demo:

b.h

typedef struct {
    int n;
    char s[8];
} Bridged;

Bridged *make_b(void);

b.c

#include <stdlib.h>
#include <string.h>
#include "b.h"

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 b.h
$ clang -O2 -c b.c -o b.c.o
$ xcrun swiftc b.o b.c.o -o b

Run:

$ ./b
Optional("foobarz")

Quick hack to retrieve message String 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()
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!