Passing structure from perl to C.

P

Prathap

Hi:

I'm writing an application that requires perl to pass some data to C
function as a structure.
I have this structure in C:
struct test
{
int t1;
int t2;
}

The C function addStruct will add the contents of fields t1 and t2
and will return the result.
The C function addStruct takes pointer to structure as an input.

How do I make perl pass the data as pointer to structure kind of
variable?
I was trying with declaring a similar hash variable and passing the
hash referance to C function,
but it does not work.

I'm using perlxstut mechanism to get perl interact with C.

Please guide me to get this working.

Regards,
Prathap
 
X

Xho Jingleheimerschmidt

Prathap said:
Hi:

I'm writing an application that requires perl to pass some data to C
function as a structure.
I have this structure in C:
struct test
{
int t1;
int t2;
}

The C function addStruct will add the contents of fields t1 and t2
and will return the result.


What on earth for? Perl can add two numbers pretty well. I assume this
is some kind of pedagogical effort, but I don't know what it is that
you want to learn. The problem with unrealistic examples is that what
might work for them might not work for the real one you have in mind.
The C function addStruct takes pointer to structure as an input.

How do I make perl pass the data as pointer to structure kind of
variable?

I'd use a wrapper. (This is for Inline, not XS)

int addStruct_wrapper(int t1, int t2) {
struct test t;
t.t1=t1;
t.t2=t2;
return addStruct(&t);
};

Xho
 
P

Prathap

What on earth for?  Perl can add two numbers pretty well.  I assume this
is some kind of pedagogical effort, but  I don't know what it is that
you want to learn.  The problem with unrealistic examples is that what
might work for them might not work for the real one you have in mind.



I'd use a wrapper.  (This is for Inline, not XS)

int addStruct_wrapper(int t1, int t2) {
   struct test t;
   t.t1=t1;
   t.t2=t2;
   return addStruct(&t);

};

Xho

Thanks for the reply.
How do I access the members of the structure that the C routinue
returns in Perl.

Regards,
Prathap
 
S

sln

Thanks for the reply.
How do I access the members of the structure that the C routinue
returns in Perl.

Regards,
Prathap

I ain't exactly sure what that guy who mentioned a wrapper and his
example whas doing there. Doing c++ for about 25 years
and perl for a few, still his syntax and prototyping seems a mix
of both. Don't know what Inline is, must be a perl thing.

The barriers between the two languages are artificially induced,
a frankenstien hypred depending on which side of the compilation
(c - the include file nightmare and perl lib nightmare) and perl
having to load that lib/dll(if it does dll).

Thats why I don't take my mind down that dark alley. Neither should
you because there is no reward on the other side. Unless you are
doing something substantial in c side where the basic thrust of
your effort is on that side, the back and forth interface overhead
will substantially slow down performance on incremental tasks
permeated over time.

-sln
 
S

sisyphus

How do I access the members of the structure that the C routinue
returns in Perl.

I'm not sure I understand the question correctly, but here's a
complete script that answers what I *think* that question asks (and
utilises what Xho already gave you):

#########################################
use warnings;
use strict;

use Inline C => Config =>
BUILD_NOISY => 1;

use Inline C => <<'EOC';

typedef struct {
int t1;
int t2;
} Test;

int addStruct(Test * t) {
int ret = t->t1 + t-> t2;
return ret;
}

int addStruct_wrapper(int t1, int t2) {
Test t;
t.t1=t1;
t.t2=t2;
return addStruct(&t);
}

void return_members(int t1, int t2) {
Inline_Stack_Vars; /* dXSARGS */
Test t;
t.t1=t1;
t.t2=t2;
Inline_Stack_Reset; /* sp = mark */
Inline_Stack_Push(sv_2mortal(newSViv(t.t1))); /* XPUSHs() */
Inline_Stack_Push(sv_2mortal(newSViv(t.t2))); /* XPUSHs() */
Inline_Stack_Done; /* PUTBACK */
Inline_Stack_Return(2); /* XSRETURN(2) */
}

EOC

my $x = addStruct_wrapper(5, 7);
print "$x\n";
my @x = return_members(9, 23);
print "@x\n";
#########################################

With Inline::C installed, check out 'perldoc Inline::C-Cookbook' for
further examples.

Note that Inline::C is essentially the same as XS - it's just an
automated procedure that generates the XS code from the C code
supplied, compiles that XS code, and then runs the perl code.

Cheers,
Rob
 
S

sln

I'm not sure I understand the question correctly, but here's a
complete script that answers what I *think* that question asks (and
utilises what Xho already gave you):

#########################################
use warnings;
use strict;

use Inline C => Config =>
BUILD_NOISY => 1;

use Inline C => <<'EOC';

typedef struct {
int t1;
int t2;
} Test;

int addStruct(Test * t) {
int ret = t->t1 + t-> t2;
return ret;
}

int addStruct_wrapper(int t1, int t2) {
Test t;
t.t1=t1;
t.t2=t2;
return addStruct(&t);
}

void return_members(int t1, int t2) {
Inline_Stack_Vars; /* dXSARGS */
Test t;
t.t1=t1;
t.t2=t2;
Inline_Stack_Reset; /* sp = mark */
Inline_Stack_Push(sv_2mortal(newSViv(t.t1))); /* XPUSHs() */
Inline_Stack_Push(sv_2mortal(newSViv(t.t2))); /* XPUSHs() */
Inline_Stack_Done; /* PUTBACK */
Inline_Stack_Return(2); /* XSRETURN(2) */
}

EOC

my $x = addStruct_wrapper(5, 7);
print "$x\n";
my @x = return_members(9, 23);
print "@x\n";
#########################################

With Inline::C installed, check out 'perldoc Inline::C-Cookbook' for
further examples.

Note that Inline::C is essentially the same as XS - it's just an
automated procedure that generates the XS code from the C code
supplied, compiles that XS code, and then runs the perl code.

Cheers,
Rob

Its 'sissy C' for people who think perl is

-sln
 
S

sisyphus

That made me laugh :)

Always delighted to introduce a little cheer into the world ;-)
When you're translating from Inline back to real
XS macros in order to understand it, I really have to wonder if it's
worth the effort :).

I've often wondered why Ingy went to the trouble of writing those
Inline_Stack_* definitions. (I guess they have mnemonic properties
that the XS macros don't, but I generally use the XS macros these days
in my Inline::C code.)
The translation was done simply to save anyone (who didn't know what
the Inline_Stack_* definitions are) the trouble of digging through the
C.pm source.

Cheers,
Rob
 
X

Xho Jingleheimerschmidt

Prathap said:
Thanks for the reply.
How do I access the members of the structure that the C routinue
returns in Perl.


I wouldn't. I carefully arranged for it to happen that C never returns
a struct test * to Perl. If you return a pointer to Perl, then it AFAIK
it will have to get cast to a void *, rather than a specific pointer,
and then from there will get recast to an int of the appropriate size.
Now you have this thing in Perl, that is a struct test * but as far as
Perl knows it is just an integer. And just who is responsible for
deciding when it should be freed and actually doing the freeing?

I really don't want to deal with crap like that on a regular basis. If
I did, I'd just stick with C in the first place rather than using Perl
and trying to interface them together in a messy hodge-podge.

If I really needed to do this, there are several different ways I could
choose from. You could return a list of values, and interpret it
positionally, like Sisyphus showed. Or return a list of name value
pairs and assign it to a hash. Or define a getter method for each
element of the struct (which requires you to deal with naked pointers in
Perl, ugh). Which one I chose would depend the exact situation. Your
exact situation seems to be adding two integers, which I wouldn't try to
accomplish by juggling back and forth between Perl and C in the first place.

use Inline C;
my $x=addStruct_ptr(8,9);
print get_t1($x);

__END__
__C__
struct test
{
int t1;
int t2;
} test;

void * addStruct_ptr(int t1, int t2) {
struct test *t;
t=(struct test *) malloc(sizeof(struct test));
t->t1=t1;
t->t2=t2;
return t;
};

int get_t1(void * x) {
return ((struct test *)x)->t1;
};



Xho
 
S

sln

I wouldn't. I carefully arranged for it to happen that C never returns
a struct test * to Perl. If you return a pointer to Perl, then it AFAIK
it will have to get cast to a void *, rather than a specific pointer,
and then from there will get recast to an int of the appropriate size.
Now you have this thing in Perl, that is a struct test * but as far as
Perl knows it is just an integer. And just who is responsible for
deciding when it should be freed and actually doing the freeing?

I really don't want to deal with crap like that on a regular basis. If
I did, I'd just stick with C in the first place rather than using Perl
and trying to interface them together in a messy hodge-podge.

If I really needed to do this, there are several different ways I could
choose from. You could return a list of values, and interpret it
positionally, like Sisyphus showed. Or return a list of name value
pairs and assign it to a hash. Or define a getter method for each
element of the struct (which requires you to deal with naked pointers in
Perl, ugh). Which one I chose would depend the exact situation. Your
exact situation seems to be adding two integers, which I wouldn't try to
accomplish by juggling back and forth between Perl and C in the first place.

use Inline C;
my $x=addStruct_ptr(8,9);
print get_t1($x);

__END__
__C__
struct test
{
int t1;
int t2;
} test;

void * addStruct_ptr(int t1, int t2) {
struct test *t;
t=(struct test *) malloc(sizeof(struct test));
t->t1=t1;
t->t2=t2;
return t;
};

int get_t1(void * x) {
return ((struct test *)x)->t1;
};



Xho


typedef struct _test
{
int t1;
int t2;
} TEST, *PTEST;

void *addStruct_ptr( int t1, int t2)
{
PTEST ptest = (PTEST) malloc( sizeof(TEST));
ptest->t1 = t1;
ptest->t2 = t2;
return (void *) ptest;
}

int get_t1(void *x)
{
PTEST ptest = (PTEST x);
return ptest->t1;
}

Yeah right, void *x, sure ... lol
At a casual glance it might be more readable like
this imo.

-sln
 
S

sln

typedef struct _test
{
int t1;
int t2;
} TEST, *PTEST;

void *addStruct_ptr( int t1, int t2)
{
PTEST ptest = (PTEST) malloc( sizeof(TEST));
ptest->t1 = t1;
ptest->t2 = t2;
return (void *) ptest;
}

int get_t1(void *x)
{
PTEST ptest = (PTEST x);
(PTEST) x;
yeah right, sure.. but who cares about unsafe typecasts,
valid ptrs and mallocs out of nowhere, deallocation, sure ... lol
-sln
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,997
Messages
2,570,240
Members
46,828
Latest member
LauraCastr

Latest Threads

Top