Skip to content

Latest commit

 

History

History
318 lines (220 loc) · 7 KB

struct.pod

File metadata and controls

318 lines (220 loc) · 7 KB

NAME

Accessing C Structs from Parrot

DESCRIPTION

Parrot provides two PMC classes to deal with C structures. These are UnManagedStruct and ManagedStruct. The former has no allocated memory and is typically used to access structures returned by NCI calls, while the latter can be used to define a structure and pass it over to a C function - pointers to structures in both cases of course.

Structure definition

The Struct PMCs take an array of triples per structure element, either as initializer or with the assign opcode to define the struct elements.

Datatype

The datatype is defined by constants declared in datatypes.pasm.

Array Size

The second initializer item, if set to a value greater then 1, defines the struct element to consist of an array of the given data type.

Byte Offset

The third initializer is the byte offset of the data item in the structure. This entry can be 0 if packing of the structure is aligned to the item's sizes or the alignment is the item's size. Otherwise these offsets must be set correctly as Parrot doesn't know how your C compiler packs arbitrary data. Parrot only knows the size of each item.

Alignment

Parrot tries to do The Right Thing that is currently align items at their size.

struct {
  char c;
  int  i;
}

The i above is aligned at 4 (for i386 or such).

Example

The C structure

struct {
  double d;
  float  f;
  int    i[4];
  char  *s;
};

can be declared with this initializer:

Named Structure Elements

The initializer can be an OrderedHash PMC too. When all elements are defined in the correct order this can be used to define and access struct elements by name and by index:

Size of a Structure

For ManagedStruct (a new structure passed over to a C function) the storage for data items has to be allocated. This is done automatically, when the initializer is attached to the Struct PMC.

The size can be obtained by:

Accessing Structure Items

Setting or getting items is done by keyed access to the Struct PMC. The first key is the structure item, an optional second key can access the n-th array element.

Example

Strings

When passing a STRING to a structure that needs a 0-terminated C-string (char *s), then you have to provide the terminating NUL char in the string.

struct {
  ...
  char *s;
};

Please also note, that the C function currently gets a pointer to string memory, so any code that might trigger GC should be avoided (or GC turned off). Passing constant strings like above is safe though.

Callback Functions in the C Library

Given a C function that returns a structure containing a callback function like in this example:

static struct {
    int (*f)(char *);
} t = {
     call_back
};
return &t;

The PASM would look like:

Nested Structures or Pointers to Nested Structures

Each contained structure needs its own UnManagedStruct initializer. The UnManagedStruct of the contained structures has to be attached to the structure type PMC as the property "_struct".

If a C function returns a pointer to this structure:

static struct xt {
    char x;
    struct yt {
          char i;
          int  j;
    } _y;
    char z;
} _x;

... access to elements could look like:

If the structure has a pointer to another structure the datatype is:

Passing A Structure to a C function

For a shared library libnci_test.so (or whatever) and a C function

typedef struct _dfi_t {
  double d;
  float  f;
  int    i[4];
} dfi_t;

int nci_ip(dfi_t *p) {}

a pointer to the structure is passed with the p signature char: