2014-06-05 19 views
8

Scusate per il titolo, non riesco a trovare le parole per descrivere la mia domanda in poche parole.Uso rapido c struct

So già che swift può usare struct scritto in c. Ad esempio

colmare-header.h

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

quindi posso utilizzare direttamente Pointer.

Ma nel mio caso, ho una libreria scritta in C. Ci sono molte strutture con lo strumento nascosto. Per esempio:
In bridging-header.h

typedef struct Pointer Pointer; 

non posso usare l'indicatore più, ha ottenuto tipo sconosciuto. Nella mia biblioteca puntatore viene utilizzato come

create_pointer(Pointer **pointer); 

Ogni aiuto è apprezzato!

P.S Non ho il file .h che definisce struct Pointer. Tutti i dettagli sul puntatore è nascondere, accedervi per funzione, per esempio

int getx(Pointer *pointer); 

Ecco il mio codice di prova completa:
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 darmi questo errore: Pointer undefined

+1

Come un addendum alla mia risposta aggiornato, sembra che le strutture possono essere problematico. Ho esaminato i documenti Swift nel seme Xcode e non riesco a trovare nulla che parla esplicitamente di inizializzare le strutture tipate e di utilizzarle. Lascio la mia risposta nella speranza che possa aiutare qualcuno a cercare di chiamare le funzioni C, ma le strutture sono ancora un'area grigia, a quanto pare. – alesplin

risposta

1

Si dovrebbe essere OK se si include l'intestazione originale in cui Pointer è typedef-ed in ___ Colmare-header.h

Quindi, per esempio se hai foo.h dove dichiari la tua struct e le tue funzioni, allora invece di fare altre chiamate typdef nella tua intestazione di bridging solo #import foo.h

Poi il tuo Codice Swift dovrebbe essere in grado di vedere i simboli dichiarati nel foo.h

Aggiornamento:

Quello che vi serve:

  1. Say "foo.h" è il file di intestazione in cui Pointer è typedef-ed . Dite anche che "foo.c" è il file in cui è implementato createPointer().
  2. Avrai bisogno di creare un progetto Swift in Xcode. Aggiungi "foo.h" e "foo.c" al progetto.
  3. Aggiungere un file di intestazione al progetto denominato "foo-Bridging-Header.h" (A volte Xcode chiede se si desidera creare un'intestazione di bridging quando si aggiunge un file .c o .m al progetto, ma con lo sviluppatore Seme che non ho ancora notato che questo è consistente).
  4. In "foo-Bridging-header.h", avrete bisogno di #include foo.h
  5. Una volta fatto questo, si dovrebbe essere in grado di chiamare uno dei simboli da "foo.h" dal "principale. veloce "nel tuo progetto.

Ad esempio, ho un progetto Swift. In questo progetto ho un file Swift (main.swift), un header C (test.h), un file sorgente C (test.c) e un Bridging Header (test-Bridging-Header.h).

loro contenuti sono i seguenti:

  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() 

Quando viene eseguito, questo uscite:

Hello, World! 
foo 
+0

Il più importante è che non ho .h che definisce la struttura, solo il .h con typedef. – galilio

+0

Giusto. Questo è quello che vuoi includere nella tua intestazione di bridging. – alesplin

+0

Ho provato ma non sono riuscito. puoi dare qualcosa come passo dopo passo? – galilio

0

Dopo il cambiamento la mia domanda , Ho una risposta

Quando la struct implementa nel nascosto, questo è chiamato "opaco"

modo da poter utilizzare COpaquePointer.

var pointer: COpaquePointer = COpaquePointer.null() 
// some init code. 
init_pointer(pointer); 
+0

Il tuo codice funzionerà come questo codice C: 'Puntatore * puntatore = NULL; init_pointer (pointer); ' Ciò rende il punto' pointer' in nessun punto della memoria e porta 'init_pointer()' all'errore di memoria. – kroisse

+0

Se Swift non conosce la forma della struttura C, ci dovrebbero essere diverse funzioni in C che sanno come allocarlo, inizializzarlo e distruggerlo. – kroisse

9

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)") 
+0

Proprio quello che stavo cercando! L'involucro è probabilmente il modo più sicuro, anche se un po 'fastidioso. – Ephemera