bbcannon [10/06/02 10:35 -0600]:
> I do know the size of the array before hand since I create it in perl
> first. I am a rookie when it comes to C, so thanks a million.
Right... I meant the C compiler needs to know at compile time. Even if you
know, that doesn't mean it will know. For example,
----8<----
use strict;
use constant SIZE => 10;
use Inline C => <<'END';
AV*
mkary(int size) {
double foo[size];
}
END
mkary(SIZE);
---->8----
That will be a compile error. Even though it's obvious to humans that the
array "foo" will always have 10 elements in it, the C compiler doesn't know
where "size" is coming from, so it doesn't know how big to make foo when it's
compiling it.
> In the Big Picture, I am just trying to pass a perl array
> to C because I can then interface to Matlab's Math and Graphics libraries.
One way to get around this is to dynamically generate your C
code. But a much simpler way is what I've already suggested.
> Is there a more efficient/easy way to send an array or array_ref to Inline
> C?
This is the best way to do it, I think. The only thing you have to check is
that you only accept arrays with numeric types. No nested structures (unless
you add code for that explicitly).
Note: I haven't tried this code, but it looks okay. You probably want to do
something like it. The API leaves something to be desired: it takes an
arrayref and returns a list... but you get the idea.
----8<----
use Inline C;
my @array = (10, 11, 12);
my @xformed = do_something(\@array);
__DATA__
__C__
void
transform_array(SV* ref) {
int i, nelems;
double *c_ary;
AV *ary;
if (SvROK(ref) && SvTYPE(SvRV(ref)) == SVt_PVAV) {
ary = (AV*)SvRV(ref);
nelems = av_len(ary) + 1;
New(0, c_ary, nelems, double);
SAVEFREEPV(c_ary);
for (i = 0; i < nelems; ++i) {
SV *elem, **tmp = av_fetch(ary, i, 0);
if (!tmp)
croak("Error fetching array index %i", i);
elem = *tmp;
c_ary[i] = SvNV(elem);
}
/* Operate on c_ary here. Do whatever it is you need to do */
matlab_foozle(c_ary, nelems);
/* Depending on your application, you could either save the values of
* 'c_ary' back into 'ref', or you can build a new list to return to
* the application. */
for (i = 0; i < nelems; ++i)
XPUSHs(sv_2mortal(newSVnv(c_ary[i])));
XSRETURN(nelems);
}
else
croak("Not an array ref");
}
---->8----
Later,
Neil