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, using the "with" capability in Inline 0.68+.
53
54 use PDL::LiteF;
55
56 $x = myfloatseq(); # exercise our C piddle constructor
57
58 print $x->info,"\n";
59
60 use Inline with => 'PDL';
61 use Inline C;
62 Inline->init; # useful if you want to be able to 'do'-load this script
63
64 __DATA__
65
66 __C__
67
68 static pdl* new_pdl(int datatype, PDL_Indx dims[], int ndims)
69 {
70 pdl *p = PDL->pdlnew();
71 PDL->setdims (p, dims, ndims); /* set dims */
72 p->datatype = datatype; /* and data type */
73 PDL->allocdata (p); /* allocate the data chunk */
74
75 return p;
76 }
77
78 pdl* myfloatseq()
79 {
80 PDL_Indx dims[] = {5,5,5};
81 pdl *p = new_pdl(PDL_F,dims,3);
82 PDL_Float *dataf = (PDL_Float *) p->data;
83 PDL_Indx i; /* dimensions might be 64bits */
84
85 for (i=0;i<5*5*5;i++)
86 dataf[i] = i; /* the data must be initialized ! */
87 return p;
88 }
89
90 Wrapping your own data into a piddle
91 Sometimes you obtain a chunk of data from another source, for example
92 an image processing library, etc. All you want to do in that case is
93 wrap your data into a piddle struct at the C level. Examples using this
94 approach can be found in the IO modules (where FastRaw and FlexRaw use
95 it for mmapped access) and the Gimp Perl module (that uses it to wrap
96 Gimp pixel regions into piddles). The following script demonstrates a
97 simple example:
98
99 use PDL::LiteF;
100 use PDL::Core::Dev;
101 use PDL::Graphics::PGPLOT;
102
103 $y = mkpiddle();
104
105 print $y->info,"\n";
106
107 imag1 $y;
108
109 use Inline with => 'PDL';
110 use Inline C;
111 Inline->init;
112
113 __DATA__
114
115 __C__
116
117 /* wrap a user supplied chunk of data into a piddle
118 * You must specify the dimensions (dims,ndims) and
119 * the datatype (constants for the datatypes are declared
120 * in pdl.h; e.g. PDL_B for byte type, etc)
121 *
122 * when the created piddle 'npdl' is destroyed on the
123 * Perl side the function passed as the 'delete_magic'
124 * parameter will be called with the pointer to the pdl structure
125 * and the 'delparam' argument.
126 * This gives you an opportunity to perform any clean up
127 * that is necessary. For example, you might have to
128 * explicitly call a function to free the resources
129 * associated with your data pointer.
130 * At the very least 'delete_magic' should zero the piddle's data pointer:
131 *
132 * void delete_mydata(pdl* pdl, int param)
133 * {
134 * pdl->data = 0;
135 * }
136 * pdl *p = pdl_wrap(mydata, PDL_B, dims, ndims, delete_mydata,0);
137 *
138 * pdl_wrap returns the pointer to the pdl
139 * that was created.
140 */
141 typedef void (*DelMagic)(pdl *, int param);
142 static void default_magic(pdl *p, int pa) { p->data = 0; }
143 static pdl* pdl_wrap(void *data, int datatype, PDL_Indx dims[],
144 int ndims, DelMagic delete_magic, int delparam)
145 {
146 pdl* npdl = PDL->pdlnew(); /* get the empty container */
147
148 PDL->setdims(npdl,dims,ndims); /* set dims */
149 npdl->datatype = datatype; /* and data type */
150 npdl->data = data; /* point it to your data */
151 /* make sure the core doesn't meddle with your data */
152 npdl->state |= PDL_DONTTOUCHDATA | PDL_ALLOCATED;
153 if (delete_magic != NULL)
154 PDL->add_deletedata_magic(npdl, delete_magic, delparam);
155 else
156 PDL->add_deletedata_magic(npdl, default_magic, 0);
157 return npdl;
158 }
159
160 #define SZ 256
161 /* a really silly function that makes a ramp image
162 * in reality this could be an opaque function
163 * in some library that you are using
164 */
165 static PDL_Byte* mkramp(void)
166 {
167 PDL_Byte *data;
168 int i; /* should use PDL_Indx to support 64bit pdl indexing */
169
170 if ((data = malloc(SZ*SZ*sizeof(PDL_Byte))) == NULL)
171 croak("mkramp: Couldn't allocate memory");
172 for (i=0;i<SZ*SZ;i++)
173 data[i] = i % SZ;
174
175 return data;
176 }
177
178 /* this function takes care of the required clean-up */
179 static void delete_myramp(pdl* p, int param)
180 {
181 if (p->data)
182 free(p->data);
183 p->data = 0;
184 }
185
186 pdl* mkpiddle()
187 {
188 PDL_Indx dims[] = {SZ,SZ};
189 pdl *p;
190
191 p = pdl_wrap((void *) mkramp(), PDL_B, dims, 2,
192 delete_myramp,0); /* the delparam is abitrarily set to 0 */
193 return p;
194 }
195
197 The Core struct -- getting at PDL core routines at runtime
198 PDL uses a technique similar to that employed by the Tk modules to let
199 other modules use its core routines. A pointer to all shared core PDL
200 routines is stored in the $PDL::SHARE variable. XS code should get
201 hold of this pointer at boot time so that the rest of the C/XS code can
202 then use that pointer for access at run time. This initial loading of
203 the pointer is most easily achieved using the functions
204 "PDL_AUTO_INCLUDE" and "PDL_BOOT" that are defined and exported by
205 "PDL::Core::Dev". Typical usage with the Inline module has already been
206 demonstrated:
207
208 use Inline with => 'PDL';
209
210 In earlier versions of "Inline", this was achieved like this:
211
212 use Inline C => Config =>
213 INC => &PDL_INCLUDE,
214 TYPEMAPS => &PDL_TYPEMAP,
215 AUTO_INCLUDE => &PDL_AUTO_INCLUDE, # declarations
216 BOOT => &PDL_BOOT; # code for the XS boot section
217
218 The code returned by "PDL_AUTO_INCLUDE" makes sure that pdlcore.h is
219 included and declares the static variables to hold the pointer to the
220 "Core" struct. It looks something like this:
221
222 print PDL_AUTO_INCLUDE;
223
224 #include <pdlcore.h>
225 static Core* PDL; /* Structure holds core C functions */
226 static SV* CoreSV; /* Gets pointer to Perl var holding core structure */
227
228 The code returned by "PDL_BOOT" retrieves the $PDL::SHARE variable and
229 initializes the pointer to the "Core" struct. For those who know their
230 way around the Perl API here is the code:
231
232 perl_require_pv ("PDL/Core.pm"); /* make sure PDL::Core is loaded */
233 #ifndef aTHX_
234 #define aTHX_
235 #endif
236 if (SvTRUE (ERRSV)) Perl_croak(aTHX_ "%s",SvPV_nolen (ERRSV));
237 CoreSV = perl_get_sv("PDL::SHARE",FALSE); /* SV* value */
238 if (CoreSV==NULL)
239 Perl_croak(aTHX_ "We require the PDL::Core module, which was not found");
240 PDL = INT2PTR(Core*,SvIV( CoreSV )); /* Core* value */
241 if (PDL->Version != PDL_CORE_VERSION)
242 Perl_croak(aTHX_ "[PDL->Version: \%d PDL_CORE_VERSION: \%d XS_VERSION: \%s] The code needs to be recompiled against the newly installed PDL", PDL->Version, PDL_CORE_VERSION, XS_VERSION);
243
244 The "Core" struct contains version info to ensure that the structure
245 defined in pdlcore.h really corresponds to the one obtained at runtime.
246 The code above tests for this
247
248 if (PDL->Version != PDL_CORE_VERSION)
249 ....
250
251 For more information on the Core struct see PDL::Internals.
252
253 With these preparations your code can now access the core routines as
254 already shown in some of the examples above, e.g.
255
256 pdl *p = PDL->pdlnew();
257
258 By default the C variable named "PDL" is used to hold the pointer to
259 the "Core" struct. If that is (for whichever reason) a problem you can
260 explicitly specify a name for the variable with the "PDL_AUTO_INCLUDE"
261 and the "PDL_BOOT" routines:
262
263 use Inline C => Config =>
264 INC => &PDL_INCLUDE,
265 TYPEMAPS => &PDL_TYPEMAP,
266 AUTO_INCLUDE => &PDL_AUTO_INCLUDE 'PDL_Corep',
267 BOOT => &PDL_BOOT 'PDL_Corep';
268
269 Make sure you use the same identifier with "PDL_AUTO_INCLUDE" and
270 "PDL_BOOT" and use that same identifier in your own code. E.g.,
271 continuing from the example above:
272
273 pdl *p = PDL_Corep->pdlnew();
274
275 Some selected core routines explained
276 The full definition of the "Core" struct can be found in the file
277 pdlcore.h. In the following the most frequently used member functions
278 of this struct are briefly explained.
279
280 · "pdl *SvPDLV(SV *sv)"
281
282 · "pdl *SetSV_PDL(SV *sv, pdl *it)"
283
284 · "pdl *pdlnew()"
285
286 "pdlnew" returns an empty pdl object that needs further
287 initialization to turn it into a proper piddle. Example:
288
289 pdl *p = PDL->pdlnew();
290 PDL->setdims(p,dims,ndims);
291 p->datatype = PDL_B;
292
293 · "pdl *null()"
294
295 · "SV *copy(pdl* p, char* )"
296
297 · "void *smalloc(STRLEN nbytes)"
298
299 · "int howbig(int pdl_datatype)"
300
301 · "void add_deletedata_magic(pdl *p, void (*func)(pdl*, int), int
302 param)"
303
304 · "void allocdata(pdl *p)"
305
306 · "void make_physical(pdl *p)"
307
308 · "void make_physdims(pdl *p)"
309
310 · "void make_physvaffine(pdl *p)"
311
312 · "void qsort_X(PDL_Xtype *data, PDL_Indx a, PDL_Indx b)" and "void
313 qsort_ind_X(PDL_Xtype *data, PDL_Indx *ix, PDL_Indx a, PDL_Indx
314 b)"
315
316 where X is one of B,S,U,L,F,D and Xtype is one of Byte, Short,
317 Ushort, Long, Float or Double. PDL_Indx is the C integer type
318 corresponding to appropriate indexing size for the perl
319 configuration (ivsize and ivtype). It can be either 'long' or
320 'long long' depending on whether your perl is 32bit or 64bit
321 enabled.
322
323 · "float NaN_float" and "double NaN_double"
324
325 These are constants to produce the required NaN values.
326
327 · "void pdl_barf(const char* pat,...)" and "void pdl_warn(const
328 char* pat,...)"
329
330 These are C-code equivalents of "barf" and "warn". They include
331 special handling of error or warning messages during pthreading
332 (i.e. processor multi-threading) that defer the messages until
333 after pthreading is completed. When pthreading is complete, perl's
334 "barf" or "warn" is called with the deferred messages. This is
335 needed to keep from calling perl's "barf" or "warn" during
336 pthreading, which can cause segfaults.
337
338 Note that "barf" and "warn" have been redefined (using
339 c-preprocessor macros) in pdlcore.h to "PDL->barf" and
340 "PDL->warn". This is to keep any XS or PP code from calling perl's
341 "barf" or "warn" directly, which can cause segfaults during
342 pthreading.
343
344 See PDL::ParallelCPU for more information on pthreading.
345
347 PDL
348
349 Inline
350
351 Handy macros from pdl.h
352 Some of the C API functions return "PDL_Anyval" C type which is a
353 structure and therefore requires special handling.
354
355 You might want to use for example "get_pdl_badvalue" function:
356
357 /* THIS DOES NOT WORK! (although it did in older PDL) */
358 if( PDL->get_pdl_badvalue(a) == 0 ) { ... }
359
360 /* THIS IS CORRECT */
361 double bad_a;
362 ANYVAL_TO_CTYPE(bad_a, double, PDL->get_pdl_badvalue(a));
363 if( bad_a == 0 ) { ... }
364
365 In pdl.h there are the following macros for handling PDL_Anyval from C
366 code:
367
368 ANYVAL_TO_SV(out_SV, in_anyval)
369 ANYVAL_FROM_CTYPE(out_anyval, out_anyval_type, in_variable)
370 ANYVAL_TO_CTYPE(out_variable, out_ctype, in_anyval)
371 ANYVAL_EQ_ANYVAL(x, y)
372
373 As these macros where not available in older PDL versions you might
374 want to add the following defines into your C/XS code to make
375 compatible with older PDL versions.
376
377 #if PDL_CORE_VERSION < 12
378 #define ANYVAL_TO_SV(outsv,inany) outsv = newSVnv((NV)(inany)
379 #define ANYVAL_FROM_CTYPE(outany,avtype,inval) outany = (PDL_Double)(inval)
380 #define ANYVAL_TO_CTYPE(outval,ctype,inany) outval = (ctype)(inany)
381 #define ANYVAL_EQ_ANYVAL(x,y) (x == y)
382 #endif
383
385 This manpage is still under development. Feedback and corrections are
386 welcome.
387
389 Copyright 2013 Chris Marshall (chm@cpan.org).
390
391 Copyright 2010 Christian Soeller (c.soeller@auckland.ac.nz). You can
392 distribute and/or modify this document under the same terms as the
393 current Perl license.
394
395 See: http://dev.perl.org/licenses/
396
397
398
399perl v5.30.2 2020-04-02 API(1)