Inline C

P

PerlNovice

Below is the message from Tassilo that shows how to work the XS
module. I did exactly what he said and it is not working for me.
When I run: perl Makefile.PL && make; I get an error:
Writing Makefile for Hello::World
make: Error -- rem: The system cannot find the file specified.
make: Error code -1
I have no idea what this means and why it occurs.

I also tried Inline C and I get the following error:
Undefined subroutine &main::hello called at ./test_inline.pl line 4.

Can someone please help!


Tassilo's posting:
Another alternative way is using pure XS. Inline::C/C++ are just
wrappers around XS. They look simpler but they aren't really. XS has
the
advantage that development happens in a more standard way: You work on
the .xs file and use another console to do a 'make'. Errors are thus
appearing on your console and not dumped in files in a hidden
directory
(as Inline does it).

When working with XS, you usually have the overhead of creating a real
module. But that's not really a bad thing. You start with h2xs:

ethan@ethan:~/Projects$ h2xs -c -b 5.5.3 -n Hello::World
Writing Hello/World/ppport.h
Writing Hello/World/World.pm
Writing Hello/World/World.xs
Writing Hello/World/Makefile.PL
Writing Hello/World/README
Writing Hello/World/t/1.t
Writing Hello/World/Changes
Writing Hello/World/MANIFEST

This creates a skeletal module with all required files. The -b switch
adds a compatibility layer to your module so that the newer portions
of
the PerlAPI will be made compatible with at least 5.00503 (for this
case).

After that, you add the functionality to Hello/World/World.xs. Right
now
it only contains:

#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"

#include "ppport.h"


MODULE = Hello::World PACKAGE = Hello::World

Adding an XS function that prints its argument as string looks like:

void
hello(string)
SV *string;
PPCODE:
printf("hello, %s\n", SvPV_nolen(string));

You put this below the 'MODULE =' line. Now you go to the other
console
and do a 'perl Makefile.PL && make':

ethan@ethan:~/Projects/Hello/World$ perl Makefile.PL && make
Checking if your kit is complete...
Looks good
Writing Makefile for Hello::World
cp World.pm blib/lib/Hello/World.pm
AutoSplitting blib/lib/Hello/World.pm (blib/lib/auto/Hello/World)
/usr/bin/perl /usr/lib/perl5/5.8.0/ExtUtils/xsubpp -typemap
/usr/lib/perl5/5.8.0/ExtUtils/typemap World.xs > World.xsc && mv
World.xsc World.c
Please specify prototyping behavior for World.xs (see perlxs manual)
cc -c -I. -O3 -march=athlon -fno-strict-aliasing -D_LARGEFILE_SOURCE
-D_FILE_OFFSET_BITS=64 -O2 -DVERSION=\"0.01\" -DXS_VERSION=\"0.01\"
-fpic "-I/usr/lib/perl5/5.8.0/i686-linux/CORE" World.c
Running Mkbootstrap for Hello::World ()
chmod 644 World.bs
rm -f blib/arch/auto/Hello/World/World.so
LD_RUN_PATH="" cc -shared -L/usr/local/lib World.o -o
blib/arch/auto/Hello/World/World.so
chmod 755 blib/arch/auto/Hello/World/World.so
cp World.bs blib/arch/auto/Hello/World/World.bs
chmod 644 blib/arch/auto/Hello/World/World.bs
Manifying blib/man3/Hello::World.3

And now, you can already call your function without installing the
module:

ethan@ethan:~/Projects/Hello/World$ perl -Mblib -MHello::World
Hello::World::hello("world");
__END__
hello, world
ethan@ethan:~/Projects/Hello/World$

If you do a 'make install' you have this module properly installed
system-wide.

Since it's a proper module, you have a file Hello/World/World.pm, too.
This is an ordinary Perl module file. If you want your function to be
exported automatically, you do it there:

@EXPORT = qw(hello);

After doing 'make' again (whenever you change something, do a 'make'),
you call it thusly:

ethan@ethan:~/Projects/Hello/World$ perl -Mblib -MHello::World
hello("world");
__END__
hello, world
ethan@ethan:~/Projects/Hello/World$

In the above command-lines, -Mblib tells perl to use the blib/
directory
as location of the module. blib/ holds the compiled but not yet
installed module.

XS does the same conversions as Inline::C, so the function hello()
could
also be written as:

void
hello(string)
char *string;
PPCODE:
printf("hello, %s\n", string);

Returning values from a function isn't hard either:

char *
hello_concat(string)
char *string;
PREINIT:
char *retstring;
int len;
CODE:
len = strlen(string) + 8;
New(0, retstring, len, char);
memcpy(retstring, "hello, ", 7);
memcpy(retstring + 7, string, strlen(string));
retstring[len] = 0;
RETVAL = retstring;
OUTPUT:
RETVAL

Just as you can pass in Perl types and do the conversion yourself, you
can use the Perl stack explicitely to return a SV. That way, you can
return lists of values by XPUSH()ing them and then telling perl how
many
values you pushed with XSRETURN(num_of_values):

void
hello_stack(string)
char *string;
PREINIT:
SV *retval;
PPCODE:
retval = newSVpv("hello, ", 7);
SvGROW(retval, strlen(string));
sv_catpv(retval, (const char*)string);

/* sv_2mortal() makes the SV mortal:
* that is, it will auto-destroy itself when it goes
* out of scope */
XPUSHs(sv_2mortal(retval));
XSRETURN(1);

I can't much comment on SWIG. From the XS/Inline/SWIG trio I'd say it
is
the worst choice since it's not Perl specific. It may make the first
steps of wrapping a library into a Perl module easier, but you have
better control over what happens when using Inline or XS. If you
ignore
the common myths that Inline is much easier than all the rest, XS is
still the best way of accessing C/C++ from Perl.

The manpages you should read are:

perlxstut /* a tutorial, not complete but helpful nonetheless */
perlguts /* explains the concepts behind the Perl internals */
perlxs
perlcall /* if you call Perl code from your XS */
perlapi
perlapio /* the I/O related PerlAPI */

Tassilo
--
 
T

Tassilo v. Parseval

Also sprach PerlNovice:
Below is the message from Tassilo that shows how to work the XS
module. I did exactly what he said and it is not working for me.
When I run: perl Makefile.PL && make; I get an error:
Writing Makefile for Hello::World
make: Error -- rem: The system cannot find the file specified.
make: Error code -1
I have no idea what this means and why it occurs.

Neither have I. To me this looks as though your environment is somewhat
borked. What operating system are you using?

Have you been able to install Perl modules containing XS portions in the
past at all? The above already failed before any compilation was
attempted. Maybe something wrong with your make program?
I also tried Inline C and I get the following error:
Undefined subroutine &main::hello called at ./test_inline.pl line 4.

You haven't shown us how test_inline.pl looks, therefore making a proper
diagnosis is tricky.

Tassilo
 

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

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,065
Latest member
OrderGreenAcreCBD

Latest Threads

Top