I want to pass swift String to c function in swift 5 .
String in swift
var key = "zxcvbnmqwertyui"
var error = "noerror"
C function declaration
extern KeyRef key(char* p0, char** p1);
C Function declaration in swift
public func key(_ p0: UnsafeMutablePointer<Int8>!, _ p1: UnsafeMutablePointer<UnsafeMutablePointer<Int8>?>!) -> KeyRef
Question : How can i pass swift string (i.e key and error) to c function (i.e key ) ?
Hello!
It looks like parts of this answer may have been discussed by @eskimo and @John_McCall on another thread, but I also thought I would provide some insight here in case it helped.
On the C side of the codebase setup the C files and expose the needed functions to Swift using a bridging header. If you start a Swift project and add C or ObjC files to it Xcode will ask if you want to generate a bridging header for your project.
C_String.c
void key_function(char *p0, char **p1) {
printf("po: %s \n", p0);
printf("p1: %s \n", *p1);
}
As mentioned above, the bridging header is the place to expose C functions, or C header files with many functions, to Swift.
SwiftString-Bridging-Header.h
// Add C Function here or optionally add C headers here.
extern void key_function(char *p0, char **p1);
In the Swift side of the codebase I am suggesting working with an NSString to provide a NULL terminated UTF8 representation of the string that UnsafeMutablePointer can use to create CChar's from and then send over to the key_function() in C.
Main.swift
// Swift Strings
var key: NSString = "zxcvbnmqwertyui"
var error: NSString = "noerror"
// Convert the Swift strings to CChars (or Int8) that map to
var key_p0 = UnsafeMutablePointer<CChar>(mutating: key.utf8String)
var error_p1 = UnsafeMutablePointer<CChar>(mutating: error.utf8String)
// Pass the character pointers over to the key_function() function in C.
key_function(key_p0, &error_p1)
I hope this helps!
michelf
(Michel Fortin)
3
I think you should also use withExtendedLifetime on the two strings to make sure they aren't prematurely deallocated. Those UnsafeMutablePointer will not retain the strings.
1 Like
@agnosticdev Thanks for replying , your solution worked .
1 Like
@shivam201312 no problem at all. Glad to help out!
Frery
(Frery Carino)
7
hello, you can also convert String to UnsafeMutablePointer by using pure swift.
var key = "some strings here"
var key_p0 = UnsafeMutablePointer<CChar>(mutating: key.cString(using: .utf8))
Here are APIs from Apple Documentation
/// The C 'char' type.
///
/// This will be the same as either `CSignedChar` (in the common
/// case) or `CUnsignedChar`, depending on the platform.
public typealias CChar = Int8
/// Returns a representation of the string as a C string
/// using a given encoding.
public func cString(using encoding: String.Encoding) -> [CChar]?
/// Creates a mutable typed pointer referencing the same memory as the given
/// immutable pointer.
///
/// - Parameter other: The immutable pointer to convert.
public init(mutating other: UnsafePointer<Pointee>)
eskimo
(Quinn “The Eskimo!”)
8
you can also convert String to UnsafeMutablePointer by using pure
Swift.
The code you posted is not safe. When you build it with a modern version of Swift (I’m using Xcode 12.0, that is, Swift 5.3) you get this warning:
…/main.swift:5:14: warning: initialization of 'UnsafeMutablePointer<CChar>' (aka 'UnsafeMutablePointer<Int8>') results in a dangling pointer
var key_p0 = UnsafeMutablePointer<CChar>(mutating: key.cString(using: .utf8))
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
See The Peril of the Ampersand for my explanation as to why.
Some Swift engineers spoke about issues at WWDC 2020 and I strongly encourage you to watch their videos:
Share and Enjoy
Quinn “The Eskimo!” @ DTS @ Apple
5 Likes
Frery
(Frery Carino)
9
Okay, i will focus on it. Thank you for your correct.