Using Swift to reference an external C function call that uses pointers - swift

Being new to Xcode, I am trying to make use of an external C call that use pointers, and I’m having difficulty finding a way to reference them in Swift. The original call in C is defined as:
int32 FAR PASCAL swe_calc(double tjd, int ipl, int32 iflag, double *xx, char *serr)
where xx is a pointer to an array of 6 Doubles and serr is a pointer to any error message(s)
Swift sees it as:
int32 swe_calc(tjd: Double, ipl: Int32, iflag: int32, xx: UnsafeMutablePointer<Double>, serr: UnsafeMutablePointer<Int8>)
(from: https://github.com/dwlnetnl/SwissEphemeris/tree/master/SwissEphemeris)
The closest thing I’ve tried that even comes close is:
var serr : UnsafeMutablePointer<Int8> = nil; // returns any error messages from the call
var x = [Double](count: 6, repeatedValue: 0); // array of 6 doubles returned from the call
var xx : UnsafeMutablePointer<Double> ;
xx = &x
swe_calc(2436647.0003794227, 4, 258, xx, serr)
println("xx = \(x[0]), \(x[1]), \(x[2]), \(x[3]), \(x[4]), \(x[5]), errors (if any)=\(serr)")
The line xx=&x gives the error
Cannot assign a value of type input[(Double)] to a value of type ‘UnsafeMutablePointer’
I need a way to get/reference/use the values returned from xx into an array of 6 doubles, and serr should definitely not be an Int8, but a string instead. (I can get the other Java and C# versions to work, but Swift has me stumped.)
How can I make the swe_calc call to give it what it needs, and get out what I need?

You were close. Both UnsafeMutablePointer parameters need an
array of the appropriate type passed as "inout argument" with &:
var x = [Double](count: 6, repeatedValue: 0);
var serr = [Int8](count: 1024, repeatedValue: 0)
let result = swe_calc(2436647.0003794227, 4, 258, &x, &serr)
Of course the arrays must be allocated large enough as expected by
the C function.
If that function puts a NUL-terminated error string into the buffer
pointed to by serr then you can convert it to a Swift string with:
let errorString = String.fromCString(&serr)

Related

Why can I pass [UInt8] type to the UnsafePointer<UInt8> type parameter?

We all know that [UInt8] type is not equal UnsafePointer<UInt8>,
But why can I pass [UInt8] type to UnsafePointer<UInt8> type parameter:
let p = UnsafeMutablePointer<UInt8>.allocate(capacity: 4)
p.initialize(repeating: 0, count: 4)
let ary:[UInt8] = [1,2,3,4]
p.assign(from: ary, count: 4) // It's OK, why?
As shown above,p.assign method frist parameter type is UnsafePointer<T>, but It's OK when I pass the type [UInt8]...
Why is that? Thanks! ;)
It's just a shortcut.
An unsafe pointer is effectively a C array: what we are pointing at is the first address of a contiguous block of memory. Therefore Swift gives you some nice help for when you have a Swift array from which you want to write to the memory: this Swift array is nothing whatever like a C array, but nevertheless, you can pass a pointer to the Swift array or even the Swift array itself, including an array literal, and Swift will just do the right thing.

How to get an array from a C function in Swift?

I am working with a C function in my Swift code that outputs an array. The function doesn't return an array because, apparently in C, functions are discouraged from returning arrays. Therefore, the function takes an in-out parameter (as a pointer) and places the array there.
The C function:
void kRing(H3Index origin, int k, H3Index* out);
H3Index* is the out parameter that takes the array. However, how do I get the array from this function in Swift? H3Index*, the out parameter, points to an integer. And, apparently in C, you can point to an integer, pass that pointer to a function, and that function can place an array in that pointer's place (even though it's pointing to an integer).
But because of Swift's type safety, this makes it difficult to get the array from the function. The Swift version:
kRing(origin: H3Index, k: Int32, out: UnsafeMutablePointer<H3Index>!)
My Swift implementation:
let h3Index: H3Index = 600022775385554943 // integer
let k: Int32 = 2 // integer
var result = H3Index() // the in-out parameter (must be integer to satisfy Swift's type safety)
_ = withUnsafeMutablePointer(to: &result) { kRing(h3Index, k, $0) }
print(result)
And it prints the result (with a bad access error, which I don't care about right now). But the result is an integer when it should be an array. How is this done?
The C implementation, for reference:
H3Index indexed = 0x8a2a1072b59ffffL; // 64-integer (hex)
int k = 2; // integer
int maxNeighboring = maxKringSize(k); // integer
H3Index* neighboring = calloc(maxNeighboring, sizeof(H3Index)); // the out parameter (a pointer to an integer and/or array)
kRing(indexed, k, neighboring); // the function
for (int i = 0; i < maxNeighboring; i++) {
if (neighboring[i] != 0) {
// iterate through array
}
}
In C,
H3Index* neighboring = calloc(maxNeighboring, sizeof(H3Index));
kRing(indexed, k, neighboring);
allocates memory for maxNeighboring elements of type H3Index and initializes the memory to zero. The address of that memory block (which is the address of the first element) is then passed to the kRing function.
It is possible to call calloc and free from Swift, but the easier to use API is Unsafe(Mutable)(Buffer)Pointer with its allocate() and deallocate() methods:
let neighboring = UnsafeMutableBufferPointer<H3Index>.allocate(capacity: maxNeighboring)
neighboring.initialize(repeating: 0)
kRing(indexed, k, neighboring.baseAddress)
Now you can print the values with
for i in 0..<maxNeighboring { print(neighboring[i]) }
or justs (because Unsafe(Mutable)BufferPointer is a collection that can be iterated over):
for neighbor in neighboring { print(neighbor) }
Eventually you must release the memory to avoid a memory leak:
neighboring.deallocate()
A simpler solution is to define a Swift array, and pass the address of the element storage to the C function:
var neighboring = Array<H3Index>(repeating: 0, count: maxNeighboring)
kRing(indexed, k, &neighboring)
for neighbor in neighboring { print(neighbor) }
neighboring is a local variable now, so that the memory is automatically released when the variable goes out of scope.

Pointer dereferencing Swift

In C & Objective C, we used to dereference a pointer and get the value as follows:
p->a = 1
or int x = p->a
But I can't find an equivalent in Swift. I have a return type UnsafePointer to AudioStreamBasicDescription? whose member values I need to read.
You use the pointee property on your UnsafePointer to access the memory it points to. So your C example would read as let x = p.pointee.a.

Swift type casting and parenthesis

Both of this type casting works
Edit
(as written by Nate Cook this is not a real Type Casting, in Swift type casting is done with the as keyword. With the following call I'm initializing an Int64 with a Float parameter.)
anInt = Int64(aFloat)
anInt = (Int64)(aFloat)
First
var anInt : Int64 = 0
var aFloat : Float = 11.5
anInt = Int64(aFloat)
println(anInt) // this prints 11
Second
var anInt : Int64 = 0
var aFloat : Float = 11.5
anInt = (Int64)(aFloat)
println(anInt) // this prints 11
In the second example the main difference is that there are parenthesis around the type Int64, but I don't find any information about this syntax in the docs.
The statement Int64(aFloat) is a typical initializer call that creates an Int64 passing a Float as the initialization parameters. Is this correct?
What is the meaning of the parenthesis in (Int64)(aFloat)? Is for better readability or there is another meaning?
Thanks
It looks like you can add an arbitrary number of parentheses (e.g. (((Int64)))). The main reason for the parentheses is to make a cast like (object as SomeClass).method()
See the duplicate question, but the short answer is that (Int) declares a tuple containing a single Int, which is semantically identical, per language specification, to a single Int Int.

How does PyNumber_Float handle an argument that is already a float?

Documentation for PyNumber_Float (here) doesn't specify what happens if you pass in a PyObject* that points to another float.
e.g.
PyObject* l = PyLong_FromLong( 101 );
PyObject* outA = PyNumber_Float(l);
outA will point to a newly created float PyObject
(or if there already exists one with that value, I think it will point to that and just increment the reference counter)
However,
PyObject* f = PyFloat_FromDouble( 1.1 );
PyObject* outB = PyNumber_Float(f);
What happens here?
Does it simply return the same pointer?
Does it first increment the reference count and then return the same pointer?
Or does it return a pointer to a new PyObject?
Is the behaviour guaranteed to be identical for the equivalent C-API calls for generating other primitives, such as Long, String, List, Dict, etc?
Finally, should the documentation clarify this situation? Would it be reasonable to file a doc-bug?
Thanks to haypo on the dev IRC channel, the following test shows that it returns the same object, with the reference counter incremented:
>>> x=1.1
>>> y=float(x)
>>> y is x, sys.getrefcount(x)-1, sys.getrefcount(y)-1
(True, 2, 2)
>>> y+=1
>>> y is x, sys.getrefcount(x)-1, sys.getrefcount(y)-1
(False, 1, 1)
Note: explanation of why refcount is one-too-high here
Note: x is y compares the memory address, "x is y" is the same as "id(x) == id(y)"
Of course it is possible that some assignment-operator optimisation is bypassing the application of float()