1API(1) User Contributed Perl Documentation API(1)
2
3
4
6 PDL::API - making piddles from Perl and C/XS code
7
9 A simple cookbook how to create piddles manually. It covers both the
10 Perl and the C/XS level. Additionally, it describes the PDL core
11 routines that can be accessed from other modules. These routines
12 basically define the PDL API. If you need to access piddles from C/XS
13 you probably need to know about these functions.
14
16 use PDL;
17 sub mkmypiddle {
18 ...
19 }
20
22 Sometimes you want to create a piddle manually from binary data. You
23 can do that at the Perl level. Examples in the distribution include
24 some of the IO routines. The code snippet below illustrates the
25 required steps.
26
27 use Carp;
28 sub mkmypiddle {
29 my $class = shift;
30 my $pdl = $class->new;
31 $pdl->set_datatype($PDL_B);
32 my @dims = (1,3,4);
33 my $size = 1;
34 for (@dims) { $size *= $_ }
35 $pdl->setdims([@dims]);
36 my $dref = $pdl->get_dataref();
37
38 # read data directly from file
39 open my $file, '<data.dat' or die "couldn't open data.dat";
40 my $len = $size*PDL::Core::howbig($pdl->get_datatype);
41 croak "couldn't read enough data" if
42 read( $file, $$dref, $len) != $len;
43 close $file;
44 $pdl->upd_data();
45
46 return $pdl;
47 }
48
50 The following example creates a piddle at the C level. We use the
51 "Inline" module which is really the way to interface Perl and C these
52 days. Note the use of the "PDL_INCLUDE", "PDL_TYPEMAP",
53 "PDL_AUTO_INCLUDE" and "PDL_BOOT" functions that were imported from
54 "PDL::Core::Dev". They are used in conjunction with an Inline Config
55 call to ensure that the PDL typemap, the PDL include files and the PDL
56 Core routines are found during compilation and later runtime execution.
57
58 use PDL::LiteF;
59 use PDL::Core::Dev;
60
61 $a = myfloatseq(); # exercise our C piddle constructor
62
63 print $a->info,"\n";
64
65 # the reason for this config call is explained below
66 use Inline C => Config =>
67 INC => &PDL_INCLUDE, # make sure we find pdlcore.h etc
68 TYPEMAPS => &PDL_TYPEMAP, # use the PDL typemap
69 AUTO_INCLUDE => &PDL_AUTO_INCLUDE, # global declarations and includes
70 BOOT => &PDL_BOOT; # boot code to load the Core struct
71
72 use Inline C;
73 Inline->init; # useful if you want to be able to 'do'-load this script
74
75 __DATA__
76
77 __C__
78
79 static pdl* new_pdl(int datatype, PDL_Long dims[], int ndims)
80 {
81 pdl *p = PDL->pdlnew();
82 PDL->setdims (p, dims, ndims); /* set dims */
83 p->datatype = datatype; /* and data type */
84 PDL->allocdata (p); /* allocate the data chunk */
85
86 return p;
87 }
88
89 pdl* myfloatseq()
90 {
91 PDL_Long dims[] = {5,5,5};
92 pdl *p = new_pdl(PDL_F,dims,3);
93 PDL_Float *dataf = (PDL_Float *) p->data;
94 int i;
95
96 for (i=0;i<5*5*5;i++)
97 dataf[i] = i; /* the data must be initialized ! */
98 return p;
99 }
100
101 Wrapping your own data into a piddle
102 Sometimes you obtain a chunk of data from another source, for example
103 an image processing library, etc. All you want to do in that case is
104 wrap your data into a piddle struct at the C level. Examples using this
105 approach can be found in the IO modules (where FastRaw and FlexRaw use
106 it for mmapped access) and the Gimp Perl module (that uses it to wrap
107 Gimp pixel regions into piddles). The following script demonstrates a
108 simple example:
109
110 use PDL::LiteF;
111 use PDL::Core::Dev;
112 use PDL::Graphics::PGPLOT;
113
114 $b = mkpiddle();
115
116 print $b->info,"\n";
117
118 imag1 $b;
119
120 use Inline C => Config =>
121 INC => &PDL_INCLUDE,
122 TYPEMAPS => &PDL_TYPEMAP,
123 AUTO_INCLUDE => &PDL_AUTO_INCLUDE,
124 BOOT => &PDL_BOOT;
125
126 use Inline C;
127 Inline->init;
128
129 __DATA__
130
131 __C__
132
133 /* wrap a user supplied chunk of data into a piddle
134 * You must specify the dimensions (dims,ndims) and
135 * the datatype (constants for the datatypes are declared
136 * in pdl.h; e.g. PDL_B for byte type, etc)
137 *
138 * when the created piddle 'npdl' is destroyed on the
139 * Perl side the function passed as the 'delete_magic'
140 * parameter will be called with the pointer to the pdl structure
141 * and the 'delparam' argument.
142 * This gives you an opportunity to perform any clean up
143 * that is necessary. For example, you might have to
144 * explicitly call a function to free the resources
145 * associated with your data pointer.
146 * At the very least 'delete_magic' should zero the piddle's data pointer:
147 *
148 * void delete_mydata(pdl* pdl, int param)
149 * {
150 * pdl->data = 0;
151 * }
152 * pdl *p = pdl_wrap(mydata, PDL_B, dims, ndims, delete_mydata,0);
153 *
154 * pdl_wrap returns the pointer to the pdl
155 * that was created.
156 */
157 typedef void (*DelMagic)(pdl *, int param);
158 static void default_magic(pdl *p, int pa) { p->data = 0; }
159 static pdl* pdl_wrap(void *data, int datatype, PDL_Long dims[],
160 int ndims, DelMagic delete_magic, int delparam)
161 {
162 pdl* npdl = PDL->pdlnew(); /* get the empty container */
163
164 PDL->setdims(npdl,dims,ndims); /* set dims */
165 npdl->datatype = datatype; /* and data type */
166 npdl->data = data; /* point it to your data */
167 /* make sure the core doesn't meddle with your data */
168 npdl->state |= PDL_DONTTOUCHDATA | PDL_ALLOCATED;
169 if (delete_magic != NULL)
170 PDL->add_deletedata_magic(npdl, delete_magic, delparam);
171 else
172 PDL->add_deletedata_magic(npdl, default_magic, 0);
173 return npdl;
174 }
175
176 #define SZ 256
177 /* a really silly function that makes a ramp image
178 * in reality this could be an opaque function
179 * in some library that you are using
180 */
181 static PDL_Byte* mkramp(void)
182 {
183 PDL_Byte *data;
184 int i;
185
186 if ((data = malloc(SZ*SZ*sizeof(PDL_Byte))) == NULL)
187 croak("mkramp: Couldn't allocate memory");
188 for (i=0;i<SZ*SZ;i++)
189 data[i] = i % SZ;
190
191 return data;
192 }
193
194 /* this function takes care of the required clean-up */
195 static void delete_myramp(pdl* p, int param)
196 {
197 if (p->data)
198 free(p->data);
199 p->data = 0;
200 }
201
202 pdl* mkpiddle()
203 {
204 PDL_Long dims[] = {SZ,SZ};
205 pdl *p;
206
207 p = pdl_wrap((void *) mkramp(), PDL_B, dims, 2,
208 delete_myramp,0); /* the delparam is abitrarily set to 0 */
209 return p;
210 }
211
213 The Core struct -- getting at PDL core routines at runtime
214 PDL uses a technique similar to that employed by the Tk modules to let
215 other modules use its core routines. A pointer to all shared core PDL
216 routines is stored in the $PDL::SHARE variable. XS code should get
217 hold of this pointer at boot time so that the rest of the C/XS code can
218 then use that pointer for access at run time. This initial loading of
219 the pointer is most easily achieved using the functions
220 "PDL_AUTO_INCLUDE" and "PDL_BOOT" that are defined and exported by
221 "PDL::Core::Dev". Typical usage with the Inline module has already been
222 demonstrated:
223
224 use Inline C => Config =>
225 INC => &PDL_INCLUDE,
226 TYPEMAPS => &PDL_TYPEMAP,
227 AUTO_INCLUDE => &PDL_AUTO_INCLUDE, # declarations
228 BOOT => &PDL_BOOT; # code for the XS boot section
229
230 The code returned by "PDL_AUTO_INCLUDE" makes sure that pdlcore.h is
231 included and declares the static variables to hold the pointer to the
232 "Core" struct. It looks something like this:
233
234 print PDL_AUTO_INCLUDE;
235
236 #include <pdlcore.h>
237 static Core* PDL; /* Structure holds core C functions */
238 static SV* CoreSV; /* Gets pointer to perl var holding core structure */
239
240 The code returned by "PDL_BOOT" retrieves the $PDL::SHARE variable and
241 initializes the pointer to the "Core" struct. For those who know their
242 way around the Perl API here is the code:
243
244 print PDL_BOOT;
245
246 perl_require_pv ("PDL::Core"); /* make sure PDL::Core is loaded */
247 CoreSV = perl_get_sv("PDL::SHARE",FALSE); /* SV* value */
248 #ifndef aTHX_
249 #define aTHX_
250 #endif
251 if (CoreSV==NULL)
252 Perl_croak(aTHX_ "We require the PDL::Core module, which was not found");
253 PDL = INT2PTR(Core*,SvIV( CoreSV )); /* Core* value */
254 if (PDL->Version != PDL_CORE_VERSION)
255 Perl_croak(aTHX_ "The code needs to be recompiled against the newly installed PDL");
256
257 The "Core" struct contains version info to ensure that the structure
258 defined in pdlcore.h really corresponds to the one obtained at runtime.
259 The code above tests for this
260
261 if (PDL->Version != PDL_CORE_VERSION)
262 ....
263
264 For more information on the Core struct see PDL::Internals.
265
266 With these preparations your code can now access the core routines as
267 already shown in some of the examples above, e.g.
268
269 pdl *p = PDL->pdlnew();
270
271 By default the C variable named "PDL" is used to hold the pointer to
272 the "Core" struct. If that is (for whichever reason) a problem you can
273 explicitly specify a name for the variable with the "PDL_AUTO_INCLUDE"
274 and the "PDL_BOOT" routines:
275
276 use Inline C => Config =>
277 INC => &PDL_INCLUDE,
278 TYPEMAPS => &PDL_TYPEMAP,
279 AUTO_INCLUDE => &PDL_AUTO_INCLUDE 'PDL_Corep',
280 BOOT => &PDL_BOOT 'PDL_Corep';
281
282 Make sure you use the same identifier with "PDL_AUTO_INCLUDE" and
283 "PDL_BOOT" and use that same identifier in your own code. E.g.,
284 continuning from the example above:
285
286 pdl *p = PDL_Corep->pdlnew();
287
288 Some selected core routines explained
289 The full definition of the "Core" struct can be found in the file
290 pdlcore.h. In the following the most frequently used member functions
291 of this struct are briefly explained.
292
293 · "pdl *SvPDLV(SV *sv)"
294
295 · "pdl *SetSV_PDL(SV *sv, pdl *it)"
296
297 · "pdl *pdlnew()"
298
299 "pdlnew" returns an empty pdl object that needs further
300 initialization to turn it into a proper piddle. Example:
301
302 pdl *p = PDL->pdlnew();
303 PDL->setdims(p,dims,ndims);
304 p->datatype = PDL_B;
305
306 · "pdl *null()"
307
308 · "SV *copy(pdl* p, char* )"
309
310 · "void *smalloc(int nbytes)"
311
312 · "int howbig(int pdl_datatype)"
313
314 · "void add_deletedata_magic(pdl *p, void (*func)(pdl*, int), int
315 param)"
316
317 · "void allocdata(pdl *p)"
318
319 · "void make_physical(pdl *p)"
320
321 · "void make_physdims(pdl *p)"
322
323 · "void make_physvaffine(pdl *p)"
324
325 · "void qsort_X(PDL_Xtype *data, int a, int b)" and "void
326 qsort_ind_X(PDL_Xtype *data, int *ix, int a, int b)"
327
328 where X is one of B,S,U,L,F,D and Xtype is one of Byte, Short,
329 Ushort, Long, Float or Double.
330
331 · "float NaN_float" and "double NaN_double"
332
333 These are constants to produce the required NaN values.
334
336 PDL
337
338 Inline
339
341 This manpage is still under development. Feedback and corrections are
342 welcome.
343
345 Copyright (c) 2001, Christian Soeller. All Rights Reserved. This
346 module is free software. It may be used, redistributed and/or modified
347 under the same terms as PDL itself (see http://pdl.perl.org).
348
349
350
351perl v5.12.3 2009-10-17 API(1)