Passing structure from perl to C.

Discussion in 'Perl Misc' started by Prathap, Aug 5, 2009.

  1. Prathap

    Prathap Guest

    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
     
    Prathap, Aug 5, 2009
    #1
    1. Advertising

  2. Prathap wrote:
    > 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
     
    Xho Jingleheimerschmidt, Aug 6, 2009
    #2
    1. Advertising

  3. Prathap

    Prathap Guest

    On Aug 6, 8:32 am, Xho Jingleheimerschmidt <> wrote:
    > Prathap wrote:
    > > 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


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

    Regards,
    Prathap
     
    Prathap, Aug 6, 2009
    #3
  4. Prathap

    Guest

    On Wed, 5 Aug 2009 22:02:54 -0700 (PDT), Prathap <> wrote:

    >On Aug 6, 8:32 am, Xho Jingleheimerschmidt <> wrote:
    >> Prathap wrote:
    >> > 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

    >
    >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
     
    , Aug 6, 2009
    #4
  5. Prathap

    sisyphus Guest

    On Aug 6, 3:02 pm, Prathap <> wrote:

    > 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
     
    sisyphus, Aug 6, 2009
    #5
  6. Prathap

    Guest

    On Thu, 6 Aug 2009 01:24:48 -0700 (PDT), sisyphus <> wrote:

    >On Aug 6, 3:02 pm, Prathap <> wrote:
    >
    >> 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


    Its 'sissy C' for people who think perl is

    -sln
     
    , Aug 6, 2009
    #6
  7. Prathap

    sisyphus Guest

    On Aug 6, 6:39 pm, Ben Morrow <> wrote:

    > 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
     
    sisyphus, Aug 6, 2009
    #7
  8. Prathap wrote:
    > On Aug 6, 8:32 am, Xho Jingleheimerschmidt <> wrote:
    >> Prathap wrote:
    >>
    >>> 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);
    >>
    >> };
    >>

    >
    > 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
     
    Xho Jingleheimerschmidt, Aug 7, 2009
    #8
  9. Prathap

    Guest

    On Thu, 06 Aug 2009 21:01:32 -0700, Xho Jingleheimerschmidt <> wrote:

    >Prathap wrote:
    >> On Aug 6, 8:32 am, Xho Jingleheimerschmidt <> wrote:
    >>> Prathap wrote:
    >>>
    >>>> 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);
    >>>
    >>> };
    >>>

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



    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
     
    , Aug 12, 2009
    #9
  10. Prathap

    Guest

    On Wed, 12 Aug 2009 15:56:43 -0700, wrote:

    >On Thu, 06 Aug 2009 21:01:32 -0700, Xho Jingleheimerschmidt <> wrote:
    >
    >>Prathap wrote:

    >
    >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
     
    , Aug 13, 2009
    #10
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Excluded_Middle

    Pointers to structure and array of structure.

    Excluded_Middle, Oct 24, 2004, in forum: C Programming
    Replies:
    4
    Views:
    757
    Martin Ambuhl
    Oct 26, 2004
  2. Leo Nunez
    Replies:
    3
    Views:
    1,230
    Neil Kurzman
    Feb 9, 2005
  3. Replies:
    2
    Views:
    610
  4. Replies:
    9
    Views:
    25,316
    Lal Bahadur Singh
    Nov 11, 2011
  5. meisterbartsch
    Replies:
    2
    Views:
    787
    meisterbartsch
    Jun 12, 2007
Loading...

Share This Page