From: Gordan B. <go...@bo...> - 2007-06-04 14:01:32
|
On Mon, 4 Jun 2007, Steven Hirsch wrote: > >> manipulation is being done by Perl as compared to C? > > > > The number crunching on the data in the array is done in C. Perl handles > > loading the data from an external source, and then afterwards taking the > > processed data back out and feeding it to GD to generate some graphs. > > Effectively, perl loads the data, passes it to C (Perl->C array > > conversion), and when the C library is done with the data, Perl reads > > the processed data back (C->Perl conversion). > > > > Before, when I had a pure Perl implementation, this data passing > > overhead would have been insignificant (1% of the run time or so). > > However, C code is so much faster than the equivalent Perl code that now > > 2/3 of the execution time goes on this transcribing of the data. > > > > The way I am transcribing the data came from one of the examples in the > > documentation, using helper functions: > > In the Swig docs, there's an example in section 26.8.1 that illustrates > how to convert a reference to a Perl array of strings in a C char** > (malloc'ed) array. > > It should be straightforward to convert the 'in' typemap to do the same > thing with floating point values. I believe (totally untested) that you > simply need to change the allocation to: > > $1 = (float*) malloc( len * sizeof(float) ); > > and in the loop below, do something like this to copy in the values: > > $1[i] = (float) SvNV( *tv ); > > you won't want to terminate with a null value, since that could be a > legitimate data value. > > Call it from perl as: > > my @array = (...); > > your_swig_routine( \@array, scalar @array ); > > The C routine signature should be something like: > > void your_c_routine( float* array, int len ) { > int i; > for ( i=0; i<len; i++ ) { > do something with array[i]; > } > } Thanks for that. I also added another helper function to just return back a C pointer, so I only have to transcribe the array once, and get the C pointer back (as per C arrays). This, in theory, should have the advantage that all the work is done on the C side. The helper function is a simple: float *FloatCreate (float Array[]) { return Array; } Then in my perl program I do: my $DataV = MyProgram::FloatCreate(\@Array); But I get an error: TypeError in method 'FloatCreate', argument 1 of type 'float []' What did I do wrong? > There may be a way to define a typemap that can pass along both the C > array and the (derived) length to the wrapped function (avoiding the extra > Perl parm), but I'm not smart enough to figure out how. (Don't get me > started on the "fine" documentation, it's too early in the day...) I don't think the extra parameter is a big deal. At least it keeps the Perl and C function interface the same. > Don't forget to code the 'freearg' typemap! Otherwise you'll leak memory > on each call. Of course - I just need to make it work in the first place, though. :-) Thanks for your help. Gordan |