Swift Tip: OpaquePointer vs. UnsafePointer
When you're working with a C library, some pointers are imported as OpaquePointer
, but other pointers are imported as UnsafePointer<struct_type>
. The difference is found in the C header file.
When a struct person
is completely defined in the header file, any pointers to it will be imported by Swift as UnsafePointer<person>
. This means we can also dereference the pointers, and look at the contents by calling .pointee
on the pointer. For example, in the following C header file, we have full information about the person
struct:
// sample.h
typedef struct person person;
struct person {
int age;
char *first_name;
};
void person_print(person*);
When we use person_print
from Swift, it gets imported as func person_print(_: UnsafeMutablePointer<person>!)
. Because person
is in the header file, we also get a constructor for person
, and we get accessors for its properties:
let p = person(age: 33, first_name: strdup("hello"))
print("person: \(p.age)")
free(p.first_name)
Another common practice in C is to keep the struct definition incomplete. For example, consider a header file looks like this:
// sample.h
typedef struct account account;
void account_print(account*);
The header file above doesn't provide the definition of the account struct, only a typedef
. The definition is found in the implementation file, and not visible outside of sample.m
:
// sample.m
struct account {
int account_number;
char *first_name;
};
This practice is common in many libraries, such as libgit which we discussed in last week's Swift Talk episode. Because account
is only in the header file, it's called an opaque (or sometimes: incomplete) type: from the outside, we don't know anything about it.
This means that we don't get an account
initializer in Swift, we can't access an account's properties, and so on. Even in account_print
, there's no mention of the account
type. It gets imported as func account_print(_: OpaquePointer!)
. An OpaquePointer
is Swift's way of letting you know that you're dealing with, well, an opaque pointer.
In last week's Swift Talk episode we go into detail about how to work with both kinds of pointers in libgit2, including memory management and making the APIs feel at home in Swift. In our new book, Advanced Swift, we look at all the pointer types in great detail.