I think I didn't make myself clear enough in my previous email. I hope
this email does the trick. To summarize:

- I would like to have a FastReader.pm which defines the Perl
  interface and has Inline code to provide the "glue" to the C
  interface. fastreader.c would contain the "straight C" code.
- I want to be able to "gcc -o c_test_harness fastreader.c main.c"
  (i.e. no Inline glue code in fastreader.c)
- I want to be able to use Inline in FastReader.pm to call the
  functions in fastreader.c from Perl, *and* to compile fastreader.c
  into the resulting FastReader.so

On Thu, 7 Jun 2001, Brian Ingerson wrote:

> You write a custom wrapper for each function, and rearrange the
> argument passing in such a way that you end up with a beautiful Perl
> interface. This hand tweaking is a "good" thing. (This is also why
> tools like h2xs are of limited real world value.)

Okay... I'm still not quite clear on this, so let's run with an
example. For example, my old XS implementation had fastreader.c with
this function:

  int read_email(char **email,long *email_line)
  {
    ...
  }

and the FastReader.xs file would provide the mapping of the C
arguments to the Perl signature:

  ($status, $email, $email_line) = read_email();

Because the fastreader.c and FastReader.xs code was separate, I could
compile my fastreader.c file as a separate C library and write a
main.c to interface with that library and test/debug it.

Now, what I did with Inline was to write this (abbreviated)
FastReader.pm:

  @EXPORT_OK = qw( read_email );

  use Inline (C => DATA => NAME => 'Mail::Folder::FastReader',
              VERSION => '0.10');
  Inline->init;

  __DATA__
  __C__
  void read_email()
  {
    char* email;
    long email_line;

    Inline_Stack_Vars;
    Inline_Stack_Reset;

    /* ... Original code from fastreader.c file included here ... */

    Inline_Stack_Push(newSViv(1));
    Inline_Stack_Push(newSVpv(email,0));
    Inline_Stack_Push(newSVnv(email_line));
    Inline_Stack_Done;

    return;
  }

What you're saying is that if I wanted to keep my old fastreader.c
file as "straight C", I could just write wrapper functions in the
FastReader.pm file that call the functions defined in the fastreader.c
file.  This means my FastReader.pm file would look something like
this:

  @EXPORT_OK = qw( read_email );

  use Inline (C => DATA => NAME => 'Mail::Folder::FastReader',
              VERSION => '0.10');
  Inline->init;

  __DATA__
  __C__
  void read_email()
  {
    int status;
    char* email;
    long email_line;

    Inline_Stack_Vars;
    Inline_Stack_Reset;

    /* Call fastreader.c function */
    status = read_email(&email,&email_line);

    Inline_Stack_Push(newSViv(status));
    Inline_Stack_Push(newSVpv(email,0));
    Inline_Stack_Push(newSVnv(email_line));
    Inline_Stack_Done;

    return;
  }

So now my Inline code in the FastReader.pm file is providing the glue
that the FastReader.xs file used to. (Plus I don't have to learn the
XS syntax!) I assume that I need to give Inline some options so that
it knows the name of the fastreader.c file, and knows to compile it
into the FastReader.so. Also, I guess there is some way to resolve
name clash for read_email... I'll check the docs.

This example is different from the "Call an existing library from
inlined C code" example in the C cookbook. The difference is that I
want Inline to compile and link in the library code. (BTW, I'd be
happy to write up an cookbook entry once I understand the details.)

> I'd like to see some concrete ideas for ARGMAP that would really fit
> well into the different C usage cases. I doubt you'll be able to replace
> the Stack macros, but you may come up with something that's a lot easier
> and works for 75% of the usages. That would be considered added value,
> IMO.

Actually, if the wrapping technique above work, then there isn't
really a need for ARGMAP. However, I guess I should complete my
thoughts on ARGMAP. I was thinking that this C signature:

  int read_email(char **email, long *email_line, long num_skipped_emails)
  { ... }

could be mapped to this Perl signature:

  ($status, $email, $email_line) = read_email($num_skipped_emails);

using an ARGMAP like:

  ARGMAP (C => Perl):
    RET_1 => RET_1
    ARG_1 => RET_2
    ARG_2 => RET_3
    ARG_3 => ARG_1

Here RET_1 for C is a bit odd because C only allows one return value,
but I wanted to be consistent.  Using this technique, the C code is
still "straight" C.  ARGMAP separates the argument mapping logic into
a separate block, and Inline would use this to generate the wrapper
code with the Inline_Stack_* stuff.

Now that I've seen the wrapper idea, I don't like the ARGMAP idea
because:

- ARGMAP introduces new syntax that has to be learned.
- ARGMAP is likely to be complicated if it is to map fixed-length C
  argument lists to dynamically sized Perl argument/return lists.
  (When do I insert an undef into the list?  When do I compress the
  list?) Once it gets complicated, we might as well write the wrapper
  code by hand.
- ARGMAP is declarative, but the wrapping technique is imperative and
  therefore probably more familiar to programmers.

> Basically I'm hearing what I think sounds like naivety to this realm.
> That's OK. :)

I've learned that new users often have insights unclouded by
experience. :) Of course, new users should be told to RTFM when
necessary, and some level of "just get used to it" is appropriate,
but our discomfort in the current state of things leads to better
engineering designs, right?

> > Unfortunately, my suggestions may increase the learning curve of
> > Inline back to the level of XS...
>
> Don't worry. I won't let that happen. I look forward to seeing you take
> these suggestions and work through them  with us so that we can further
> refine the Inline process. I hope I didn't sound too defensive. I really
> love the collaboration of the Inline community, even if I sometimes need
> to put on the dictator's hat.

And I don't mean to sound like I'm on the offensive. :) I'm trying to
understand if what I want to do is already possible with Inline, and
if not, I'm trying to explore the design space in order to come up
with a good solution.

Regards,
David

_________________________________________________________________________
David Coppit - Ph.D. Candidate         [EMAIL PROTECTED]
The University of Virginia             http://coppit.org/
    "Yes," said Piglet, "Rabbit has Brain." There was a long silence.
"I suppose," said Pooh, "that that's why he never understands anything."

Reply via email to