1 # Copyright (C) 2001-2005, The Perl Foundation.
6 Structures - Accessing C Structs from Parrot
10 Parrot provides two PMC classes to deal with C structures. These are
11 UnManagedStruct and ManagedStruct. The former has no allocated memory and is
12 typically used to access structures returned by NCI calls, while the latter can
13 be used to define a structure and pass it over to a C function - pointers to
14 structures in both cases of course.
16 =head1 Structure definition
18 The Struct PMCs take an array of triples per structure element, either as
19 initializer or with the B<assign> opcode to define the struct elements.
25 The datatype is defined by constants declared in F<datatypes.pasm>.
29 The second initializer item, if set to a value greater then 1, defines the
30 struct element to consist of an array of the given data type.
34 The third initializer is the byte offset of the data item in the structure.
35 This entry can be 0 if packing of the structure is aligned to the item's sizes
36 or the alignment is the item's size. Otherwise these offsets must be set
37 correctly as Parrot doesn't know how your C compiler packs arbitrary data.
38 Parrot only knows the size of each item.
44 Parrot tries to do The Right Thing that is currently align items at their size.
51 The C<i> above is aligned at 4 (for i386 or such).
64 can be declared with this initializer:
66 new P2, 'ResizablePMCArray'
67 .include "datatypes.pasm"
68 push P2, .DATATYPE_DOUBLE
69 push P2, 0 # no array i.e. 1 element
70 push P2, 0 # calculate offset by just adding item size
71 push P2, .DATATYPE_FLOAT
74 push P2, .DATATYPE_INT
75 push P2, 4 # 4 elem array
77 push P2, .DATATYPE_CSTR
81 =head2 Named Structure Elements
83 The initializer can be an OrderedHash PMC too. When all elements are defined in
84 the correct order this can be used to define and access struct elements by name
88 .include "datatypes.pasm"
89 set P2["d"], .DATATYPE_DOUBLE
90 push P2, 0 # no array i.e. 1 element
91 push P2, 0 # calculate offset by just adding item size
92 set P2["f"], .DATATYPE_FLOAT
95 =head1 Size of a Structure
97 For ManagedStruct (a new structure passed over to a C function) the storage for
98 data items has to be allocated. This is done automatically, when the
99 initializer is attached to the Struct PMC.
101 The size can be obtained by:
103 new P5, 'ManagedStruct', P2 # P2 be some initializer
105 set I0, P5 # allocated size
107 =head1 Accessing Structure Items
109 Setting or getting items is done by keyed access to the Struct PMC. The first
110 key is the structure item, an optional second key can access the n-th array
115 set P5[0], N0 # set d
116 set N0, P5[0] # get d
118 set N0, P5["d"] # get d if initializer is an OrderedHash
120 set P5[1], N1 # set f
121 set N1, P5[1] # get f
122 set N1, P5["f"] # get f if initializer is an OrderedHash
124 set P5[2;0], I2 # set i[0]
125 set I3, P5[2;3] # get i[3]
127 set P5["i"; 2] # set i[2] if initializer is an OrderedHash
129 set S0, P5[3] # get string at *s
130 set S0, P5["s"] # same
134 When passing a STRING to a structure that needs a 0-terminated C-string (char
135 *s), then you have to provide the terminating NUL char in the string.
142 set P5["s"], "a string\x0"
144 Please also note, that the C function currently gets a pointer to string
145 memory, so any code that might trigger GC should be avoided (or GC turned off).
146 Passing constant strings like above is safe though.
148 set P5["s"], S0 # S0 shouldn't move until function call
150 =head2 Callback Functions in the C Library
152 Given a C function that returns a structure containing a callback function like
162 The PASM would look like:
164 push P2, .DATATYPE_FUNC_PTR
165 # attach function signature property to this type
169 setprop P1, "_signature", P3
172 # P5 is the return UnManagedStruct PMC
174 # now we get a callable NCI PMC
176 set S5, "hello call_back"
177 # call the call_back function
180 =head2 Nested Structures or Pointers to Nested Structures
182 Each contained structure needs its own UnManagedStruct initializer. The
183 UnManagedStruct of the contained structures has to be attached to the structure
184 type PMC as the property B<"_struct">.
186 If a C function returns a pointer to this structure:
197 ... access to elements could look like:
199 # the nested structure
200 new P3, 'OrderedHash'
201 set P3["i"], .DATATYPE_CHAR
204 set P3["j"], .DATATYPE_INT
207 new P4, 'UnManagedStruct', P3
210 new P2, 'OrderedHash'
211 set P2["x"], .DATATYPE_CHAR
214 set P2["_y"], .DATATYPE_STRUCT
216 # attach the unmanaged struct as property to the type PMC
217 set P1, P2[-1] # last element
218 setprop P1, "_struct", P4
221 set P2["z"], .DATATYPE_CHAR
225 # attach struct initializer to return value in P5
230 set I0, P5[1;0] # _y.i
231 set I0, P5[1;1] # _y.j
236 set I0, P5["_y"; "i"]
237 set I0, P5["_y"; "j"]
240 If the structure has a pointer to another structure the datatype is:
242 push P2, .DATATYPE_STRUCT_PTR
244 =head1 Passing A Structure to a C function
246 For a shared library B<libnci_test.so> (or whatever) and a C function
248 typedef struct _dfi_t {
254 int nci_ip(dfi_t *p) {}
256 a pointer to the structure is passed with the B<p> signature char:
258 loadlib P1, "libnci_test"
259 dlfunc P0, P1, "nci_ip", "ip"
260 # P5 is ManagedStruct from above
266 Not all datatypes are implemented. Alignment is barely tested on different
267 machines. Arrays of structures aren't handled yet. Passing nested structures to
272 F<src/pmc/unmanagedstruct.pmc>, F<src/pmc/managedstruct.pmc>
276 F<docs/pdds/pdd03_calling_conventions.pod> F<t/pmc/nci.t>, F<src/nci_test.c>
280 Leopold Toetsch <lt@toetsch.at>