1API(1)                User Contributed Perl Documentation               API(1)
2
3
4

NAME

6       PDL::API - making piddles from Perl and C/XS code
7

DESCRIPTION

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

SYNOPSIS

16         use PDL;
17         sub mkmypiddle {
18          ...
19         }
20

Creating a piddle manually from Perl

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

Creating a piddle in C

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

The gory details

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

SEE ALSO

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

BUGS

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)
Impressum