Быстрое использование c struct
Извините за название, я не могу найти слова, чтобы описать мой вопрос в нескольких словах.
Я уже знаю, что swift может использовать struct, написанную на c. Например
В Bridging-Header.h
typedef struct {
int x;
int y;
} Pointer;
тогда я могу использовать указатель напрямую.
Но в моем случае у меня есть библиотека, написанная на C. Есть много структур со скрытыми инструментами. Например:
В Briding-Header.h
typedef struct Pointer Pointer;
Я больше не могу использовать указатель, получил неизвестный тип. В моей библиотеке указатель используется как
create_pointer(Pointer **pointer);
Любая помощь приветствуется!
PS У меня нет.h файла, который определяет struct Pointer. Все подробности о указателе скрыты, например, доступ к ним осуществляется по функциям.
int getx(Pointer *pointer);
Вот мой полный тестовый код:
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 дает мне эту ошибку: указатель не определен
3 ответа
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)")
Вы должны быть в порядке, если вы включите оригинальный заголовок, где Pointer имеет typedef-ed, в ___Bridging-Header.h
Так, например, если у вас есть foo.h, где вы объявляете свою структуру и свои функции, тогда вместо выполнения каких-либо дополнительных вызовов typdef в заголовке моста просто #import foo.h
Тогда ваш код Swift должен видеть символы, объявленные в foo.h
Обновить:
Что вам нужно:
- Скажем, "foo.h" - это заголовочный файл, в котором Pointer имеет тип def-ed. Также скажите, что "foo.c" - это файл, в котором реализована функция createPointer().
- Вам нужно будет создать проект Swift в Xcode. Добавьте в проект "foo.h" и "foo.c".
- Добавьте файл заголовка к проекту с именем "foo-Bridging-Header.h" (Иногда Xcode спрашивает, хотите ли вы создать Bridging Header, когда вы добавляете файл.c или.m в проект, но с семенем разработчика, который у меня есть. пока не заметил, чтобы это было согласовано).
- В "foo-Bridging-Header.h" вам нужно
#include foo.h
- После того, как вы это сделаете, вы сможете вызывать любые символы из "foo.h" из файла "main.swift" в вашем проекте.
Например, у меня есть проект Swift. В этом проекте у меня есть файл Swift (main.swift), заголовок C (test.h), исходный файл C (test.c) и заголовок Bridging (test-Bridging-Header.h).
Их содержание таково:
- test.h:
void printFoo();
- test.c:
#include <stdio.h> #include "test.h" void printFoo() { printf("foo\n"); }
- Тест-Bridging-header.h:
#import "test.h"
- main.swift:
import Foundation println("Hello, World!") printFoo()
При запуске это выводит:
Hello, World! foo
После изменения моего вопроса я получил ответ.
Когда структура реализуется в скрытом виде, это называется "непрозрачным"
так что я могу использовать COpaquePointer.
var pointer: COpaquePointer = COpaquePointer.null()
// some init code.
init_pointer(pointer);