Tutorial 4: Nifty Types
The main task of Nifty is to generate the type conversion code that translates Erlang types into C types and vice versa. Nifty provides support for most of C datatypes with a few notable exceptions. The type information is stored in the module defining the type, with the exception of base types, which are stored in Nifty’s library module. Nifty’s type representation is in form of a string:
Base Types
The following table shows, how C types and Erlang types correspond to each other:
C Types | Erlang Types | Nifty Type Name |
---|---|---|
signed int or int |
integer() |
nifty.int |
unsigned int |
integer() |
nifty.unsigned int |
char |
integer() |
nifty.char |
short |
integer() |
nifty.short |
long |
integer() |
nifty.long |
long long |
integer() |
nifty.long long |
float |
float() |
nifty.float |
double |
float() |
nifty.double |
<type> * |
{integer(), string()} |
<module>.<type> * |
Nifty performs no check that integer values fit into the datatype. Too large integers will overflow.
Records
C records (structs) are translated into erlang records and every definition of a struct results
in a record definition. Nifty translates the values of each field according to the type
of the C record definition. Nested C records are translated into nested Erlang records.
Nifty stores the record definitions into an hrl
file which can be easily included to use
record notion.
Hint: Nifty currently does not supports anonymous structs. They are excluded from the internal type database together with all functions that depend on them.
Enums
Nifty supports enum
types. You can either use the numerical value directly or get the
numerical value associated with a given alias by calling nifty:enum_value(module, "ALIAS")
.
See this blog post for more information.
Pointer
Getting A Pointer To A Value
To get a pointer of a value Nifty provides the nifty:pointer_of/2
function. The first argument
is the value and the second argument is the Nifty Type Name of the base type:
For base types it is possible to omit the module name:
Nifty tries to find the type specification in the given module. If the specification is found, Nifty allocates memory according to the corresponding C type and stores the value in this memory area. A pointer to this memory area is then returned annotated with the correct type information.
In order to get a pointer to a pointer, it is possible to omit the type information. Nifty will then use the type information stored in the pointer:
If you need a pointer to a preallocated memory area for a certain type, but you do not care about
the containing value, you can use pointer/1
, which works like pointer_of
without initialization:
This will allocate memory of the size sizeof(type)
and return a pointer casted to the specified type.
Dereferencing A Pointer
The reverse function to nifty:pointer_of/2
is nifty:dereference
. This function takes a pointer
and translates the value it points to into an Erlang value:
This translation happens according to the type of the pointer:
Casting A Pointer To A Different Type
As shown in the previous section, it is possible to cast a pointer to a different type. nifty:as_type/2
takes a pointer and a type and returns that pointer casted to the type. as_type/2
also checks
if the type is known:
Function Pointers
Function pointers default to void *
pointers and are handled as such. That means, that you are not able to dereference
them. You can however obtain them from functions or pass them to other functions.
Memory Management
Memory Allocation And free()
Nifty’s malloc()
is nifty:malloc/1
. It works in the same way as malloc()
as it allocates the
specified amount of memory and returns a nifty.void *
pointer to it. In a similar manner Nifty’s free()
is nifty:free/1
, which deallocates the memory segment associated by the given pointer:
All of by Nifty allocated memory is not garbage collected, so make sure to free all memory you used.
Segfaults
Be careful when you are using pointers, memory allocation and so on. Like in C it is possible to access invalid or protected memory areas that result in a memory access exception more commonly known as segfault:
As you will see, a segfault will crash the Erlang runtime. You can however catch segafaults as demonstrated in the next tutorial.
Previous Tutorial | Next Tutorial |
---|