The cheesiest possible way is to ->copy the PDL before making your Inline::C 
call of course!

There is a PDL->make_physical you can call from C in the PDL core structure.  
That should take care of the segfaults, but it will give you unpredictable 
flow: affine (slice) flow will work fine since it is implemented with direct 
links into the other PDL’s ->data area, but other types (which require calling 
a function pointer in the trans structure) will not work right.  

I’ll go with everyone else here and say that you should be using Inline::Pdlpp 
unless you have a Really Good Reason not to.  If you do have a Really Good 
Reason, have a look at the flag structure (there’s an appendix about it in 
Practical Magick) and search on the flags in the core C routines in the PDL 
tree — that will point you to the Right way to trigger explicit-copy dataflow.

Good luck!

> On Jun 19, 2020, at 12:22 AM, Derek Lamb <[email protected]> wrote:
> 
> Question: Is there a straightforward way to operate on a piddle in C without 
> knowing whether it's a physical or a child piddle, just like we do in PDL?  
> And if so, what is it?
> 
> As background: I have a subroutine, implemented in C, called from Perl using 
> Inline::C.  It takes an arbitrary-sized array ref of 2D-piddles as input, and 
> modifies the piddles, like so:
> 
> ###
> my $aref = [$pdl1, $pdl2, $pdl3];
> my_sub( $aref );
> ###
> 
> So far, so good.  That is, until I accidentally threw a child (non-physical) 
> piddle at it:
> 
> ###
> my $aref = [$big_3D_pdl->dog];
> my_sub( $aref );
> ###
> 
> Then, at best, my_sub completes successfully but does not change any of the 
> data in the piddles in $aref.  Other times it segfaults.  It has no trouble 
> changing the data in $aref in the first example, when the piddles are 
> physical.
> 
> For simplicity, here is an example that doesn't use array refs, just takes a 
> single piddle as input.  When called on a physical piddle $im0, it works 
> fine, but does not change the data in $im2 and frequently segfaults.  This 
> script contains a subroutine "times_ten" that just multiplies each element of 
> the piddle by 10.
> 
> ###
> use strict;
> use warnings;
> use PDL::LiteF;
> use PDL::Core::Dev;
> use PDL::Dbg;
> $PDL::debug=1; #for px calls
> 
> my $im0 = sequence(5,4);
> my $im1 = sequence(8,7);
> my $im2 = $im1->slice("0:3,0:2");
> 
> $_->px foreach ($im0,$im2);
> 
> times_ten($im0);
> times_ten($im2);
> 
> print "\nNow that I'm done, \$im0 is:\n$im0\n";
> print "\nNow that I'm done, \$im2 is:\n$im2\n";
> 
> no strict 'subs';
> use Inline with => 'PDL';
> use Inline C;
> Inline->init; # useful if you want to be able to 'do'-load this script
> 1;
> 
> __DATA__
> 
> __C__
> 
> void times_ten(pdl* im){
> 
>    printf("im xsize = %ld, ysize = %ld\n",im->dims[0],im->dims[1]);
>    PDL_Double *data = (PDL_Double *) im->data;
>    for (PDL_Indx x = 0; x < im->dims[0]; x++){
>      for (PDL_Indx y = 0; y < im->dims[1]; y++){
>        PDL_Indx offset = x * im->dimincs[0] + y * im->dimincs[1];
>        data[offset] *= 10;
>      }
>    }
> return;
> }
> ###
> 
> What I would like is something near the beginning of the C code that 
> abstracts the input piddle so the subsequent code doesn't care whether the 
> input is physical or child.
> 
> I made a similar example using Inline::Pdlpp and looked at the generated C 
> code, and there in the subroutine "pdl_times_ten_readdata", in the THREADLOOP 
> section is code that seems to take care of the pointer addressing whether the 
> input piddle is physical or a virtual/child piddle.  I was hoping for 
> something less involved than a bunch of "__privtrans" lines—it's a bit hard 
> for the casual reader to understand what's going on.  (That "casual reader" 
> may be me, in 6 or 12 months!)  Is there a clean way to do this, or is it 
> best in this case to make sure that the input piddles are always physical?
> 
> thanks much,
> Derek
> 
> _______________________________________________
> pdl-general mailing list
> [email protected]
> https://lists.sourceforge.net/lists/listinfo/pdl-general
> 



_______________________________________________
pdl-general mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/pdl-general

Reply via email to