Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Swift use c struct

Sorry for the title, I can't find words to describe my question in few words.

I already know that swift can use struct written in c. For example

In Bridging-Header.h

typedef struct {
    int x;
    int y;
} Pointer;

then I can use Pointer directly.

But in my case, I have a library written in C. There are many structs with hidden implement. For example:
In Briding-Header.h

typedef struct Pointer Pointer;

I can't use Pointer any more, got unknown type. In my library Pointer is used as

create_pointer(Pointer **pointer);

Any help is appreciated!

P.S I have no .h file which define struct Pointer. All details about Pointer is hide, access them by function, for example

int getx(Pointer *pointer);

Here is my full test code:
user_input.c

#include <stdio.h>

#include "user_input.h"

struct Pointer {
    int x;
    int y;
};

void get_user_input(int *user_input) {
    scanf("%i", user_input);
}

void init_pointer(Pointer *point) {
    point->x = 20;
    point->y = 20;
}

user_input.h

#ifndef __user_input_h__
#define __user_input_h__

typedef struct Pointer Pointer;

void init_pointer(Pointer *p);

#endif

Bridging-Header.h

#include "user_input.h"

main.swift

import Foundation
var pointer:Pointer = Pointer(x:10, y:20)

Xcode give me this error: Pointer undefined

like image 905
galilio Avatar asked Jun 05 '14 03:06

galilio


People also ask

Can struct have functions in Swift?

Function Inside Swift StructWe can also define a function inside a swift struct. A function defined inside a struct is called a method.

Can a struct inherit Swift?

A struct cannot inherit from another kind of struct, whereas classes can build on other classes. You can change the type of an object at runtime using typecasting. Structs cannot have inheritance, so have only one type. If you point two variables at the same struct, they have their own independent copy of the data.

Can I use Swift struct in Objective-C?

Swift's Struct type is one of the most praised features of the language, but is currently unavailable in Objective-C.


2 Answers

Bridging-Header.h

#include "user_input.h"

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

import Foundation

var 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)")
like image 159
kroisse Avatar answered Oct 28 '22 10:10

kroisse


You should be OK if you include the original header where Pointer is typedef-ed in ___Bridging-Header.h

So for example if you have foo.h where you declare your struct and your functions, then instead of doing any additional typdef calls in your bridging header just #import foo.h

Then your Swift code should be able to see the symbols declared in foo.h

Update:

What you need:

  1. Say "foo.h" is the header file where Pointer is typedef-ed. Also say that "foo.c" is the file where createPointer() is implemented.
  2. You'll need to create a Swift project in Xcode. Add "foo.h" and "foo.c" to the project.
  3. Add a header file to the project called "foo-Bridging-Header.h" (Sometimes Xcode asks if you want to create a Bridging Header when you add a .c or .m file to the project, but with the Developer Seed I haven't observed this to be consistent yet).
  4. In "foo-Bridging-Header.h", you'll need to #include foo.h
  5. Once you have done this, you should be able to call any of the symbols from "foo.h" from the "main.swift" file in your project.

For example, I have a Swift project. In this project I have a Swift file (main.swift), a C header (test.h), a C source file (test.c), and a Bridging Header (test-Bridging-Header.h).

Their contents are as follows:

  1. test.h:
void
printFoo();
  1. test.c:
#include <stdio.h>
#include "test.h"

void
printFoo() {
    printf("foo\n");
}
  1. test-Bridging-Header.h:
#import "test.h"
  1. main.swift:
import Foundation

println("Hello, World!")

printFoo()

When run, this outputs:

Hello, World!
foo
like image 1
alesplin Avatar answered Oct 28 '22 10:10

alesplin