在Swift中如何使用C中的Struct

来源:互联网 发布:nosql数据库的优点 编辑:程序博客网 时间:2024/05/01 20:23

swift 无法直接访问 c 语言的Struct。只能通过指针的方式访问。


///////-----例子1开始-------////////

The c Lib API : mycapi.h

<code style="margin: 0px; padding: 0px; border: 0px; font-family: Consolas, Menlo, Monaco, "Lucida Console", "Liberation Mono", "DejaVu Sans Mono", "Bitstream Vera Sans Mono", "Courier New", monospace, sans-serif; white-space: inherit;"><span class="kwd" style="margin: 0px; padding: 0px; border: 0px; color: rgb(0, 0, 139);">typedef</span><span class="pln" style="margin: 0px; padding: 0px; border: 0px; color: black;"> </span><span class="kwd" style="margin: 0px; padding: 0px; border: 0px; color: rgb(0, 0, 139);">struct</span><span class="pun" style="margin: 0px; padding: 0px; border: 0px; color: black;">{</span><span class="pln" style="margin: 0px; padding: 0px; border: 0px; color: black;">    </span><span class="typ" style="margin: 0px; padding: 0px; border: 0px; color: rgb(43, 145, 175);">int</span><span class="pln" style="margin: 0px; padding: 0px; border: 0px; color: black;">  itype</span><span class="pun" style="margin: 0px; padding: 0px; border: 0px; color: black;">;</span><span class="pln" style="margin: 0px; padding: 0px; border: 0px; color: black;">    </span><span class="kwd" style="margin: 0px; padding: 0px; border: 0px; color: rgb(0, 0, 139);">double</span><span class="pln" style="margin: 0px; padding: 0px; border: 0px; color: black;"> </span><span class="pun" style="margin: 0px; padding: 0px; border: 0px; color: black;">*</span><span class="pln" style="margin: 0px; padding: 0px; border: 0px; color: black;"> dx</span><span class="pun" style="margin: 0px; padding: 0px; border: 0px; color: black;">;</span><span class="pln" style="margin: 0px; padding: 0px; border: 0px; color: black;">    </span><span class="kwd" style="margin: 0px; padding: 0px; border: 0px; color: rgb(0, 0, 139);">double</span><span class="pln" style="margin: 0px; padding: 0px; border: 0px; color: black;"> </span><span class="pun" style="margin: 0px; padding: 0px; border: 0px; color: black;">*</span><span class="pln" style="margin: 0px; padding: 0px; border: 0px; color: black;"> dy</span><span class="pun" style="margin: 0px; padding: 0px; border: 0px; color: black;">;</span><span class="pln" style="margin: 0px; padding: 0px; border: 0px; color: black;"></span><span class="pun" style="margin: 0px; padding: 0px; border: 0px; color: black;">}</span><span class="typ" style="margin: 0px; padding: 0px; border: 0px; color: rgb(43, 145, 175);">MyObjInfo</span><span class="pun" style="margin: 0px; padding: 0px; border: 0px; color: black;">;</span><span class="pln" style="margin: 0px; padding: 0px; border: 0px; color: black;"></span><span class="kwd" style="margin: 0px; padding: 0px; border: 0px; color: rgb(0, 0, 139);">typedef</span><span class="pln" style="margin: 0px; padding: 0px; border: 0px; color: black;"> </span><span class="typ" style="margin: 0px; padding: 0px; border: 0px; color: rgb(43, 145, 175);">MyObjInfo</span><span class="pln" style="margin: 0px; padding: 0px; border: 0px; color: black;"> </span><span class="pun" style="margin: 0px; padding: 0px; border: 0px; color: black;">*</span><span class="pln" style="margin: 0px; padding: 0px; border: 0px; color: black;"> </span><span class="typ" style="margin: 0px; padding: 0px; border: 0px; color: rgb(43, 145, 175);">MyObjHandle</span><span class="pun" style="margin: 0px; padding: 0px; border: 0px; color: black;">;</span><span class="pln" style="margin: 0px; padding: 0px; border: 0px; color: black;"></span><span class="typ" style="margin: 0px; padding: 0px; border: 0px; color: rgb(43, 145, 175);">MyObjHandle</span><span class="pln" style="margin: 0px; padding: 0px; border: 0px; color: black;"> </span><span class="typ" style="margin: 0px; padding: 0px; border: 0px; color: rgb(43, 145, 175);">MyObjInit</span><span class="pun" style="margin: 0px; padding: 0px; border: 0px; color: black;">(</span><span class="kwd" style="margin: 0px; padding: 0px; border: 0px; color: rgb(0, 0, 139);">const</span><span class="pln" style="margin: 0px; padding: 0px; border: 0px; color: black;"> </span><span class="kwd" style="margin: 0px; padding: 0px; border: 0px; color: rgb(0, 0, 139);">char</span><span class="pln" style="margin: 0px; padding: 0px; border: 0px; color: black;"> </span><span class="pun" style="margin: 0px; padding: 0px; border: 0px; color: black;">*</span><span class="pln" style="margin: 0px; padding: 0px; border: 0px; color: black;">pFile</span><span class="pun" style="margin: 0px; padding: 0px; border: 0px; color: black;">);</span></code>

add myapi.h as module

my Swift code :

<code style="margin: 0px; padding: 0px; border: 0px; font-family: Consolas, Menlo, Monaco, "Lucida Console", "Liberation Mono", "DejaVu Sans Mono", "Bitstream Vera Sans Mono", "Courier New", monospace, sans-serif; white-space: inherit;"><span class="kwd" style="margin: 0px; padding: 0px; border: 0px; color: rgb(0, 0, 139);">import</span><span class="pln" style="margin: 0px; padding: 0px; border: 0px; color: black;"> </span><span class="typ" style="margin: 0px; padding: 0px; border: 0px; color: rgb(43, 145, 175);">Foundation</span><span class="pln" style="margin: 0px; padding: 0px; border: 0px; color: black;"></span><span class="kwd" style="margin: 0px; padding: 0px; border: 0px; color: rgb(0, 0, 139);">import</span><span class="pln" style="margin: 0px; padding: 0px; border: 0px; color: black;"> mycapiModulevar h</span><span class="pun" style="margin: 0px; padding: 0px; border: 0px; color: black;">:</span><span class="typ" style="margin: 0px; padding: 0px; border: 0px; color: rgb(43, 145, 175);">MyObjHandle</span><span class="pln" style="margin: 0px; padding: 0px; border: 0px; color: black;"> </span><span class="pun" style="margin: 0px; padding: 0px; border: 0px; color: black;">=</span><span class="pln" style="margin: 0px; padding: 0px; border: 0px; color: black;"> </span><span class="typ" style="margin: 0px; padding: 0px; border: 0px; color: rgb(43, 145, 175);">MyObjInit</span><span class="pun" style="margin: 0px; padding: 0px; border: 0px; color: black;">(</span><span class="str" style="margin: 0px; padding: 0px; border: 0px; color: maroon;">"/home/a"</span><span class="pun" style="margin: 0px; padding: 0px; border: 0px; color: black;">)</span><span class="pln" style="margin: 0px; padding: 0px; border: 0px; color: black;">var o</span><span class="pun" style="margin: 0px; padding: 0px; border: 0px; color: black;">:</span><span class="typ" style="margin: 0px; padding: 0px; border: 0px; color: rgb(43, 145, 175);">MyObjInfo</span><span class="pln" style="margin: 0px; padding: 0px; border: 0px; color: black;"> </span><span class="pun" style="margin: 0px; padding: 0px; border: 0px; color: black;">=</span><span class="pln" style="margin: 0px; padding: 0px; border: 0px; color: black;"> h</span><span class="pun" style="margin: 0px; padding: 0px; border: 0px; color: black;">.</span><span class="pln" style="margin: 0px; padding: 0px; border: 0px; color: black;">memory</span><span class="com" style="margin: 0px; padding: 0px; border: 0px; color: gray;">////to do somethings</span><span class="pln" style="margin: 0px; padding: 0px; border: 0px; color: black;"></span><span class="com" style="margin: 0px; padding: 0px; border: 0px; color: gray;">//...</span><span class="pln" style="margin: 0px; padding: 0px; border: 0px; color: black;">h</span><span class="pun" style="margin: 0px; padding: 0px; border: 0px; color: black;">.</span><span class="pln" style="margin: 0px; padding: 0px; border: 0px; color: black;">destroy</span><span class="pun" style="margin: 0px; padding: 0px; border: 0px; color: black;">()</span><span class="pln" style="margin: 0px; padding: 0px; border: 0px; color: black;">h </span><span class="pun" style="margin: 0px; padding: 0px; border: 0px; color: black;">=</span><span class="pln" style="margin: 0px; padding: 0px; border: 0px; color: black;"> nilprint</span><span class="pun" style="margin: 0px; padding: 0px; border: 0px; color: black;">(</span><span class="str" style="margin: 0px; padding: 0px; border: 0px; color: maroon;">"\(o.itype)"</span><span class="pun" style="margin: 0px; padding: 0px; border: 0px; color: black;">)</span></code>
///////-----例子1结束-------////////



在C函数定义的需要使用的Struct

typedef struct my_struct {    unsigned char buffer[10];} my_struct;void my_struct_init(my_struct *my_s) {    for (int i = 0; i < 10; i++) {        my_s->buffer[i] = (char) i;    }}

In Swift, we have two options:

1. Struct on the stack

var my_s: my_struct = ...

However, we have to initialize it somehow. Every struct has a default initializer

var my_s: my_struct = my_struct(buffer: (0, 0, 0, 0, 0, 0, 0, 0, 0, 0))

Note that in this case the buffer[10] has been translated to Swift as a 10-tuple.

Now we can call:

my_struct_init(&my_s)println("Buffer: \(my_s.buffer)") // Buffer: (0, 1, 2, 3, 4, 5, 6, 7, 8, 9)

However, the more complex is the struct, the more difficult is to use the default initializer.

2. Struct on the heap

This is similar to using malloc and free in C:

var my_s_pointer = UnsafeMutablePointer<my_struct>.alloc(1)println("Buffer: \(my_s.buffer)") // Buffer: (some random values)my_struct_init(my_s_pointer)println("Buffer: \(my_s_pointer.memory.buffer)") // Buffer: (0, 1, 2, 3, 4, 5, 6, 7, 8, 9)my_s_pointer.destroy()

Combine both approaches

The following function will initialize any struct:

func initStruct<S>() -> S {    let struct_pointer = UnsafeMutablePointer<S>.alloc(1)    let struct_memory = struct_pointer.memory    struct_pointer.destroy()    return struct_memory}var my_s: my_struct = initStruct()my_struct_init(&my_s)





C Struct 转义方法

    func blankof<T>(type:T.Type) ->T {

        let ptr =UnsafeMutablePointer<T>.alloc(sizeof(T))

        let val = ptr.memory

        ptr.destroy()

        return val

    }


        var fs =blankof(C_Struct)

        test(&fs))



在bridging-header中 需要定义 在Swift中使用的Struct 文件。

Bridging-Header.h

<code style="margin: 0px; padding: 0px; border: 0px; font-family: Consolas, Menlo, Monaco, "Lucida Console", "Liberation Mono", "DejaVu Sans Mono", "Bitstream Vera Sans Mono", "Courier New", monospace, sans-serif; white-space: inherit;">#include "user_input.h"</code>

user_input.c

#include <stdlib.h>struct Pointer {    int x;    int y;};Pointer *create_pointer() {    Pointer *p = malloc(sizeof(struct Pointer));    if (p) {        p->x = 20;        p->y = 20;    }    return p;}void delete_pointer(Pointer *p) {    free(p);}int pointer_x(Pointer *p) {    return p->x;}int pointer_y(Pointer *p) {    return p->y;}

user_input.h

#ifndef __user_input_h__#define __user_input_h__typedef struct Pointer Pointer;Pointer *create_pointer();void delete_pointer(Pointer *p);int pointer_x(Pointer *p);int pointer_y(Pointer *p);#endif

main.swift

<code style="margin: 0px; padding: 0px; border: 0px; font-family: Consolas, Menlo, Monaco, "Lucida Console", "Liberation Mono", "DejaVu Sans Mono", "Bitstream Vera Sans Mono", "Courier New", monospace, sans-serif; white-space: inherit;">import Foundationvar pointer: COpaquePointer = create_pointer()println("\(pointer_x(pointer)), \(pointer_y(pointer))")delete_pointer(pointer)// Writing the wrapper class could be helpful.class CPointer {    var _ptr: COpaquePointer    init() {        _ptr = create_pointer()        assert(_ptr, "Failed on create_pointer()")    }    deinit {        delete_pointer(_ptr)    }    var x: Int {        get { return Int(pointer_x(_ptr)) }    }    var y: Int {        get { return Int(pointer_y(_ptr)) }    }}var p = CPointer()println("\(p.x), \(p.y)")</code>
                                             
0 0