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 rou‐
11 tines that can be accessed from other modules. These routines basically
12 define the PDL API. If you need to access piddles from C/XS you proba‐
13 bly 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
103 Sometimes you obtain a chunk of data from another source, for example
104 an image processing library, etc. All you want to do in that case is
105 wrap your data into a piddle struct at the C level. Examples using this
106 approach can be found in the IO modules (where FastRaw and FlexRaw use
107 it for mmapped access) and the Gimp Perl module (that uses it to wrap
108 Gimp pixel regions into piddles). The following script demonstrates a
109 simple example:
110
111 use PDL::LiteF;
112 use PDL::Core::Dev;
113 use PDL::Graphics::PGPLOT;
114
115 $b = mkpiddle();
116
117 print $b->info,"\n";
118
119 imag1 $b;
120
121 use Inline C => Config =>
122 INC => &PDL_INCLUDE,
123 TYPEMAPS => &PDL_TYPEMAP,
124 AUTO_INCLUDE => &PDL_AUTO_INCLUDE,
125 BOOT => &PDL_BOOT;
126
127 use Inline C;
128 Inline->init;
129
130 __DATA__
131
132 __C__
133
134 /* wrap a user supplied chunk of data into a piddle
135 * You must specify the dimensions (dims,ndims) and
136 * the datatype (constants for the datatypes are declared
137 * in pdl.h; e.g. PDL_B for byte type, etc)
138 *
139 * when the created piddle 'npdl' is destroyed on the
140 * Perl side the function passed as the 'delete_magic'
141 * parameter will be called with the pointer to the pdl structure
142 * and the 'delparam' argument.
143 * This gives you an opportunity to perform any clean up
144 * that is necessary. For example, you might have to
145 * explicitly call a function to free the resources
146 * associated with your data pointer.
147 * At the very least 'delete_magic' should zero the piddle's data pointer:
148 *
149 * void delete_mydata(pdl* pdl, int param)
150 * {
151 * pdl->data = 0;
152 * }
153 * pdl *p = pdl_wrap(mydata, PDL_B, dims, ndims, delete_mydata,0);
154 *
155 * pdl_wrap returns the pointer to the pdl
156 * that was created.
157 */
158 typedef void (*DelMagic)(pdl *, int param);
159 static void default_magic(pdl *p, int pa) { p->data = 0; }
160 static pdl* pdl_wrap(void *data, int datatype, PDL_Long dims[],
161 int ndims, DelMagic delete_magic, int delparam)
162 {
163 pdl* npdl = PDL->pdlnew(); /* get the empty container */
164
165 PDL->setdims(npdl,dims,ndims); /* set dims */
166 npdl->datatype = datatype; /* and data type */
167 npdl->data = data; /* point it to your data */
168 /* make sure the core doesn't meddle with your data */
169 npdl->state ⎪= PDL_DONTTOUCHDATA ⎪ PDL_ALLOCATED;
170 if (delete_magic != NULL)
171 PDL->add_deletedata_magic(npdl, delete_magic, delparam);
172 else
173 PDL->add_deletedata_magic(npdl, default_magic, 0);
174 return npdl;
175 }
176
177 #define SZ 256
178 /* a really silly function that makes a ramp image
179 * in reality this could be an opaque function
180 * in some library that you are using
181 */
182 static PDL_Byte* mkramp(void)
183 {
184 PDL_Byte *data;
185 int i;
186
187 if ((data = malloc(SZ*SZ*sizeof(PDL_Byte))) == NULL)
188 croak("mkramp: Couldn't allocate memory");
189 for (i=0;i<SZ*SZ;i++)
190 data[i] = i % SZ;
191
192 return data;
193 }
194
195 /* this function takes care of the required clean-up */
196 static void delete_myramp(pdl* p, int param)
197 {
198 if (p->data)
199 free(p->data);
200 p->data = 0;
201 }
202
203 pdl* mkpiddle()
204 {
205 PDL_Long dims[] = {SZ,SZ};
206 pdl *p;
207
208 p = pdl_wrap((void *) mkramp(), PDL_B, dims, 2,
209 delete_myramp,0); /* the delparam is abitrarily set to 0 */
210 return p;
211 }
212
214 The Core struct -- getting at PDL core routines at runtime
215
216 PDL uses a technique similar to that employed by the Tk modules to let
217 other modules use its core routines. A pointer to all shared core PDL
218 routines is stored in the $PDL::SHARE variable. XS code should get
219 hold of this pointer at boot time so that the rest of the C/XS code can
220 then use that pointer for access at run time. This initial loading of
221 the pointer is most easily achieved using the functions
222 "PDL_AUTO_INCLUDE" and "PDL_BOOT" that are defined and exported by
223 "PDL::Core::Dev". Typical usage with the Inline module has already been
224 demonstrated:
225
226 use Inline C => Config =>
227 INC => &PDL_INCLUDE,
228 TYPEMAPS => &PDL_TYPEMAP,
229 AUTO_INCLUDE => &PDL_AUTO_INCLUDE, # declarations
230 BOOT => &PDL_BOOT; # code for the XS boot section
231
232 The code returned by "PDL_AUTO_INCLUDE" makes sure that pdlcore.h is
233 included and declares the static variables to hold the pointer to the
234 "Core" struct. It looks something like this:
235
236 print PDL_AUTO_INCLUDE;
237
238 #include <pdlcore.h>
239 static Core* PDL; /* Structure holds core C functions */
240 static SV* CoreSV; /* Gets pointer to perl var holding core structure */
241
242 The code returned by "PDL_BOOT" retrieves the $PDL::SHARE variable and
243 initializes the pointer to the "Core" struct. For those who know their
244 way around the Perl API here is the code:
245
246 print PDL_BOOT;
247
248 perl_require_pv ("PDL::Core"); /* make sure PDL::Core is loaded */
249 CoreSV = perl_get_sv("PDL::SHARE",FALSE); /* SV* value */
250 #ifndef aTHX_
251 #define aTHX_
252 #endif
253 if (CoreSV==NULL)
254 Perl_croak(aTHX_ "We require the PDL::Core module, which was not found");
255 PDL = INT2PTR(Core*,SvIV( CoreSV )); /* Core* value */
256 if (PDL->Version != PDL_CORE_VERSION)
257 Perl_croak(aTHX_ "The code needs to be recompiled against the newly installed PDL");
258
259 The "Core" struct contains version info to ensure that the structure
260 defined in pdlcore.h really corresponds to the one obtained at runtime.
261 The code above tests for this
262
263 if (PDL->Version != PDL_CORE_VERSION)
264 ....
265
266 For more information on the Core struct see PDL::Internals.
267
268 With these preparations your code can now access the core routines as
269 already shown in some of the examples above, e.g.
270
271 pdl *p = PDL->pdlnew();
272
273 By default the C variable named "PDL" is used to hold the pointer to
274 the "Core" struct. If that is (for whichever reason) a problem you can
275 explicitly specify a name for the variable with the "PDL_AUTO_INCLUDE"
276 and the "PDL_BOOT" routines:
277
278 use Inline C => Config =>
279 INC => &PDL_INCLUDE,
280 TYPEMAPS => &PDL_TYPEMAP,
281 AUTO_INCLUDE => &PDL_AUTO_INCLUDE 'PDL_Corep',
282 BOOT => &PDL_BOOT 'PDL_Corep';
283
284 Make sure you use the same identifier with "PDL_AUTO_INCLUDE" and
285 "PDL_BOOT" and use that same identifier in your own code. E.g., conti‐
286 nuning from the example above:
287
288 pdl *p = PDL_Corep->pdlnew();
289
290 Some selected core routines explained
291
292 The full definition of the "Core" struct can be found in the file pdl‐
293 core.h. In the following the most frequently used member functions of
294 this struct are briefly explained.
295
296 · "pdl *SvPDLV(SV *sv)"
297
298 · "pdl *SetSV_PDL(SV *sv, pdl *it)"
299
300 · "pdl *pdlnew()"
301
302 "pdlnew" returns an empty pdl object that needs further initial‐
303 ization to turn it into a proper piddle. Example:
304
305 pdl *p = PDL->pdlnew();
306 PDL->setdims(p,dims,ndims);
307 p->datatype = PDL_B;
308
309 · "pdl *null()"
310
311 · "SV *copy(pdl* p, char* )"
312
313 · "void *smalloc(int nbytes)"
314
315 · "int howbig(int pdl_datatype)"
316
317 · "void add_deletedata_magic(pdl *p, void (*func)(pdl*, int), int
318 param)"
319
320 · "void allocdata(pdl *p)"
321
322 · "void make_physical(pdl *p)"
323
324 · "void make_physdims(pdl *p)"
325
326 · "void make_physvaffine(pdl *p)"
327
328 · "void qsort_X(PDL_Xtype *data, int a, int b)" and "void
329 qsort_ind_X(PDL_Xtype *data, int *ix, int a, int b)"
330
331 where X is one of B,S,U,L,F,D and Xtype is one of Byte, Short,
332 Ushort, Long, Float or Double.
333
334 · "float NaN_float" and "double NaN_double"
335
336 These are constants to produce the required NaN values.
337
339 PDL
340
341 Inline
342
344 This manpage is still under development. Feedback and corrections are
345 welcome.
346
348 Copyright (c) 2001, Christian Soeller. All Rights Reserved. This mod‐
349 ule is free software. It may be used, redistributed and/or modified
350 under the same terms as PDL itself (see http://pdl.perl.org).
351
352
353
354perl v5.8.8 2003-05-21 API(1)