7

I'm trying to pass a const char * to an old C library converted from a Swift string in Swift.

This is the C function I'm calling:

artnet_node artnet_new(const char *ip, int verbose) { ...

how can I convert a Swift string to this const char type? It works when I pass ipAddress like this:

internal var ipAddress = "192.168.1.43"

but dit does not work when I pass it like this

internal var ipAddress:String = "192.168.1.43"

I need this in a function where I need to specify the type:

internal func setupArtnode(ip:String) -> Int{

I tried using AnyObject instead of String but that doesn't work either.

Thanks.

Steven B.
  • 1,429
  • 2
  • 19
  • 38
  • Please add clarification on what doesn't work- compilation or execution, and any associated error messages. – sbooth Dec 24 '16 at 03:23

4 Answers4

11

You should be able to pass a String directly to a C function expecting const char * and it will be automatically converted to a null-terminated UTF-8 string:

let string = "string"
let node = artnet_new(string, 1)

See Interacting with C APIs for more information. Here is the relevant excerpt:

When a function is declared as taking an UnsafePointer argument, it can accept any of the following:

  • A String value, if Type is Int8 or UInt8. The string will automatically be converted to UTF8 in a buffer, and a pointer to that buffer is passed to the function.
sbooth
  • 16,646
  • 2
  • 55
  • 81
  • for some reason the function wont take the argument and takes the default value, i updated the question with some more info – Steven B. Dec 23 '16 at 23:01
  • your quote got me to use UnsafePointer which seemed to work, I added my working code. thanks!! – Steven B. Dec 28 '16 at 11:18
4

Not sure why but this code is working. This passes a string to a C function expecting a const char* which seems to be the same as a unsafePointer.

internal func setupArtnode(ipAddress:String) -> NSInteger{
    let cString = self.ipAddress.cString(using: String.defaultCStringEncoding)!
    let newString:String = NSString(bytes: cString, length: Int(ipAddress.characters.count), encoding:String.Encoding.ascii.rawValue)! as String
    let key2Pointer = UnsafePointer<Int8>(newString)

    node = artnet_new(key2Pointer, Int32(verbose))     // VERBOSE : true(1) , false(0)
...
Steven B.
  • 1,429
  • 2
  • 19
  • 38
2

Simple way for Swift 3

var ipAddress: String = "192.168.1.43"
var verbose: Int = 1
artnet_node artnet_new((ipAddress as NSString).utf8String, verbose)
Cao Mạnh Quang
  • 1,027
  • 11
  • 10
  • While using sqlite3 API sqlite3_bind_text() with swift, I was seeing memory corruption and weird results if the String was directly passed. `(ipAddress as NSString).utf8String` fixed this. – vine'th Oct 30 '18 at 10:15
1

You didn't specify what your Swift array contains. In any case, you need to convert your Swift array to an array of Int8:

let str = "Hello world"
let cArray = str.cString(using: .utf8)

artnet_new(cArray, 1)
Code Different
  • 90,614
  • 16
  • 144
  • 163