I tried calling a C language function from Swift.
I investigated how to pass arguments when calling a C language function from Swift. Confirmed with XCode 10.1.
For the time being, I found that in Swift & is not an address operator. Sometimes it's a good analogy, but in the case of a self-made structure, you have to convert the type properly.
c
void func1(void)
{
return;
}
swift
func1()
It's easy.
c
void func2(int a, int b)
{
return;
}
swift
func2(1,2)
This is also easy, isn't it?
c
int func3(int a, int b)
{
return a+b;
}
swift
//Print with print
print("func3()", func3(1,2))
//Assign to variable
let c = func3(7,8)
print("func3()", c)
This is also easy, isn't it?
c
void func4(const char *in, char *out)
{
unsigned long len = strlen(in) + 1;
out[0] = 'A';
memcpy(&out[1], in, len);
return;
}
swift
var outstr : [CChar] = [0, 0, 0, 0, 0, 0]
func4("1234", &outstr)
print("func4()", outstr)
print("func4()", String(cString : outstr))
If the argument is const char *` ``, passing a String literal will convert it to a C string. If the argument is `` `char *
, you have to pass a pointer to the variable.
Execution example
func4() [65, 49, 50, 51, 52, 0]
func4() A1234
c
struct location {
int x;
int y;
};
int func5(struct location loc);
c
int func5(struct location loc)
{
loc.x += 1;
loc.y += 1;
return loc.x + loc.y;
}
swift
var l = location.init(x:1,y:2)
print("fnc5()", func5(l))
You can use init () to initialize the structure.
h
struct location {
int x;
int y;
};
int func6(struct location *loc);
c
int func5(struct location loc)
{
loc.x += 1;
loc.y += 1;
return loc.x + loc.y;
}
swift
var l = location.init(x:1,y:2)
withUnsafeMutablePointer(to: &l){
let p = $0
print("func6() before", p.pointee)
func6(p)
print("func6() after", p.pointee)
}
Use withUnsafeMutablePointer () to get a pointer to a structure. The type of p is UnsafeMutablePointer
Suppose you have an encoder function written in C.
uint32_t hogeEnc(void *inp, void *outp);
Like this, a useless copy has occurred, but it worked.
func encode(data:Data) -> Data {
let input = UnsafeMutablePointer<UInt8>.allocate(capacity: 1920)
let output = UnsafeMutablePointer<UInt8>.allocate(capacity: 1920)
data.copyBytes(to: input, count: data.count)
let enclen = hogeEnc(input, output)
let encdata = Data(buffer: UnsafeMutableBufferPointer(start: output, count: Int(enclen)))
input.deinitialize(count: 1920)
output.deinitialize(count: 1920)
return encdata
}
First, generate pointers for input and output to secure space.
Copies the data type byte string of the argument to the area pointed to by the input pointer.
Calls the C encoding function.
Converts the result encoded by the encoding function to Data type. At that time, the UnsafeMutablePointer
That's all for now.
Recommended Posts