Call a C function from Swift

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.

1 No arguments, no return value

c


void func1(void)
{
    return;
}

swift


func1()

It's easy.

2 arguments int, no return value

c


void func2(int a, int b)
{
    return;
}

swift


func2(1,2)

This is also easy, isn't it?

3 argument int, return value int

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?

4 Argument char array pointer

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

5 argument structure

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.

6 Argument structure pointer

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 . Use p.pointee to refer to a structure pointer. Structure pointers are valid only in the body of withUnsafeMutablePointer ().

7 Pass the Data type as a pointer and make the output pointer a Data type.

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 type is converted to the UnsafeMutableBufferPointer type. Finally release the pointer. (I don't know if it's necessary, but just in case.) Be careful not to access outside the area reserved in C language.

That's all for now.

Recommended Posts

Call a C function from Swift
Call a program written in Swift from Processing (Java)
Make a SOAP call in C #
Call Java library from C with JNI
[Swift] A note about function and closure
How to call Swift 5.3 code from Objective-C
Convert from C String pointer to Swift String type
[Swift 5.3] Learn from A Swift Tour Swift [Xcode 12.1] <10/28 under construction>
ABC --013-A & B & C
Call Java from JRuby
ABC --036-A & B & C
ABC --010 --A & B & C
ABC --028 --A & B & C
ABC --015 --A & B & C
ABC --128 --A & B & C
ABC --012-A & B & C
ABC --018 --A & B & C
Call a method with a Kotlin callback block from Java
ABC --017 --A & B & C
ABC --029- A & B & C
ABC --022 --A & B & C
ABC --019 --A & B & C
ABC --030- A & B & C
ABC --127 --A & B & C
ABC --007 --A & B & C
Treat Swift functions and closures as C function pointers
ABC --132- A & B & C
ABC --026 --A & B & C
ABC --014- A & B & C
ABC --016 --A & B & C
ABC --031 --A & B & C
Generate models from JSON to Swift, PHP, C #, JAVA
ABC --021 --A & B & C
ABC --025 --A & B & C
ABC --024 --A & B & C
ABC --027 --A & B & C
ABC --080- A & B & C
ABC --129- A & B & C & D
ABC --133- A & B & C & D
Use C program from Ruby
ABC --122 --A & B & C & D
ABC --125- A & B & C & D
ABC --130- A & B & C & D
ABC --126 --A & B & C & D
About adding a like function
Create a name input function
Pass C ++ char * to Swift
I tried to generate a C language program source from cURL
[Swift5] How to communicate from ViewController to Model and pass a value