2014-12-31 23 views
5

Tôi đang làm việc với API của bên thứ ba c Tôi đang cố gọi một trong các hàm bằng một chuỗi đơn giản. Một cái gì đó như thế này:Chuyển đổi chuỗi thành UnsafeMutablePointer <char_t> trong Swift

some_c_func("aString"); 

tôi nhận được một lỗi build:

Type 'UnsafeMutablePointer<char_t>' does not conform to protocol 'StringLiteralConvertible' 

Tôi đã nhìn thấy một số gợi ý để sử dụng utf8 trên String hoặc chuyển đổi tương tự, mà được gần đó, nhưng với các lỗi sau:

some_c_func("aString".cStringUsingEncoding(NSUTF8StringEncoding)); 
'UnsafePointer<Int8>' is not convertible to 'UnsafeMutablePointer<char_t>' 

Tôi làm cách nào để tạo Con trỏ không an toàn?

Trả lời

1

Tất cả phụ thuộc vào những gì char_t là.

Nếu char_t chuyển thành Int8 thì thao tác sau sẽ hoạt động.

if let cString = str.cStringUsingEncoding(NSUTF8StringEncoding) { 
    some_c_func(strdup(cString)) 
} 

Điều này có thể được thu gọn để

some_c_func(strdup(str.cStringUsingEncoding(NSUTF8StringEncoding)!)) 

CẢNH BÁO! Phương pháp thứ hai này sẽ gây ra sự cố nếu func cStringUsingEncoding(_:) trả lại nil.


Đang cập nhật cho Swift 3, và để sửa chữa bộ nhớ bị rò rỉ

Nếu chuỗi C chỉ cần thiết trong một phạm vi địa phương, sau đó không strdup() là cần thiết.

guard let cString = str.cString(using: .utf8) else { 
    return 
} 

some_c_func(cString) 

cString sẽ có cùng vòng đời bộ nhớ như str (cũng tương tự ít nhất).

Nếu chuỗi C cần phải sống bên ngoài phạm vi địa phương, thì bạn sẽ cần một bản sao. Bản sao đó sẽ cần được giải thoát.

guard let interimString = str.cString(using: .utf8), let cString = strdup(interimString) else { 
    return 
} 

some_c_func(cString) 

//… 

free(cString) 
+0

Công trình này, cảm ơn! Nhưng nó không (không còn?) Yêu cầu unwrapping tùy chọn. Chữ ký trên cStringUsingEncoding là 'func cStringUsingEncoding (mã hóa: UInt) -> UnsafePointer ', và strdup chỉ chuyển đổi nó thành UnsafeMutablePointer. – brodney

+0

@brodney heh, tôi đang sử dụng công cụ Xcode 6.1.1 (6A2008a): chữ ký là 'func cStringUsingEncoding (mã hóa: NSStringEncoding) -> [CChar]?' Để hạ cấp xuống 'UnsafePointer ? ' –

+0

Sử dụng strdup, bạn sẽ phải giải phóng bộ đệm. trì hoãn {free (cString)} –

0

tôi đã không cố gắng đi qua chuỗi như vậy, nhưng tôi có một hàm C mà tôi gọi là từ Swift, mà sẽ đưa rất nhiều thông số hơn đưa ra ở đây, trong đó là một tham chiếu đến một định kiểu đệm Swift C để giữ một chuỗi lỗi. Trình biên dịch không phàn nàn và hàm gọi hoạt động. Hy vọng rằng điều này sẽ chỉ đạo bạn gần hơn với câu trả lời và bạn có thể cung cấp một bản cập nhật với câu trả lời cuối cùng hoặc người khác có thể.

var err = [CChar](count: 256, repeatedValue: 0) 
    var rv = somefunc((UnsafeMutablePointer<Int8>)(err)) 

    if (rv < 0) { 
     println("Error \(err)") 
     return 
    } 
1

nó có thể được đơn giản hơn thế - nhiều API C vượt qua chuỗi xung quanh như char * loại và xử lý nhanh chóng những là không an toàn.

thử cập nhật C API (tốt) hoặc hack các tệp tiêu đề của nó (xấu) để khai báo chúng dưới dạng const char *.

theo kinh nghiệm của tôi, điều này cho phép bạn chuyển các loại chuỗi nhanh chóng chuẩn trực tiếp đến API C.

dường như là hằng số là bắt buộc để phù hợp với giao thức.

+0

Tuyệt vời! Bạn giúp tôi rất nhiều với điều đó. Tôi đã mất nhiều bối cảnh vì chuyển đổi chuỗi thành UnsafeMutablePointer và ngược lại. strdup trông rất bẩn trong nhanh chóng, và không dễ dàng để dealloc (và nơi để dealloc). TK –

Các vấn đề liên quan