Presentation is loading. Please wait.

Presentation is loading. Please wait.

Embedding Perl in C and the other way around

Similar presentations


Presentation on theme: "Embedding Perl in C and the other way around"— Presentation transcript:

1 Embedding Perl in C and the other way around
Marian Co-Founder and CIO of 1H Ltd.

2 Embedding C in Perl Why would I want to do that?
Get some performance by using native C for some of the processing Embed parts of your existing C application into your Perl app without rewriting it completely

3 The XS way... It cannot be seen, cannot be felt,
Cannot be heard, cannot be smelt. It lies behind stars and under hills, And empty holes it fills. - J.R.R. Tolkien, The Hobbit Answer: dark. XS is an interface description file format used to create an extension interface between Perl and C code extremely hard to learn even the smallest program must be implemented as additional module There is another, similar way using SWIG... I don't know how it works :( If someone is interested...

4 perlman:perlxstut man perlxs man perlguts man perlapi man h2xs
XS Docs perlman:perlxstut man perlxs man perlguts man perlapi man h2xs .

5 XS Basics SV – Scalar Value SV* newSVsv(SV*); AV – Array Value
HV – Hash Value IV – Integer Value SV* newSViv(IV); UV – Unsigned Integer Value SV* newSVuv(UV); NV – Double Value SV* newSVnv(double); PV – String Value SV* newSVpv(const char*, STRLEN); SV* newSVpvn(const char*, STRLEN); SV* newSVpvf(const char*, ...); SvIV(SV*) SvUV(SV*) SvNV(SV*) SvPV(SV*, STRLEN len) SvPV_nolen(SV*) Scalar, Hash and Arrays are typedefs which can include any of the following types. You create the value with the coresponding newSV* function. You access the value with the coresponding Sv* function.

6 Inline::C $ cat inline.pl #!/usr/bin/perl use Inline C=>'
void some_func() { printf("Hello World\n"); }'; &some_func $ ./inline.pl Hello World Examples from Inline::C-Cookbook Describe the way we add and execute the C code.

7 fun way of using Inline::C
$ cat perl-sign.pl #!/usr/bin/perl use Inline C=>' void C() { int m,u,e=0;float l,_,I; for(;1840-e;putchar((++e>907&&942>e?61- drahnreB"])) for(u=_=l=0;79-(m=e%80)&&I*l+_*_<6&&26- ++u;_=2*l*_+e/80*.09-1,l=I) I=l*l-_*_-2+m/27.; }'; &C

8 mmmmmmmmooooooooooooooooooooooooocccccccccc. is@zrre i
i.cccccccoooooooooommmmm mmmmmmoooooooooooooooooooooooccccccccccc.....iiscrr zMesii....cccccoooooooooom erccsiiiii..ccccooooooooo uMeu r e e eci..cccooooooo ooooooooooccccccc..iiiiiiiiiiiiisscz z s..cccoooooo bnneree eci..ccccooooo occcccccc.....iisccrnb m nci..ccccooooo cii..cccccoooo Bernhard ercsi...cccccoooo rnz esi...cccccoooo ( esi..ccccooooo bneze es..cccoooooo urcsi..cccoooooo zsi..cccooooooo nu er eznri.cccoooooooo rrsii.....ccccoooooooooom rrcsi....ccccccoooooooooomm mmmmmmmmoooooooooooooooooooooooocccccccccc....iisceeeusi..cccccccooooooooommmmm

9 Multiple Return Values
print map {"$_\n"} get_localtime(time); use Inline C => <<'END_OF_C_CODE'; #include <time.h> void get_localtime(int utc) { struct tm *ltime = localtime(&utc); Inline_Stack_Vars; Inline_Stack_Reset; Inline_Stack_Push(sv_2mortal(newSViv(ltime->tm_year))); Inline_Stack_Push(sv_2mortal(newSViv(ltime->tm_mon))); Inline_Stack_Push(sv_2mortal(newSViv(ltime->tm_mday))); Inline_Stack_Push(sv_2mortal(newSViv(ltime->tm_hour))); Inline_Stack_Push(sv_2mortal(newSViv(ltime->tm_min))); Inline_Stack_Push(sv_2mortal(newSViv(ltime->tm_sec))); Inline_Stack_Push(sv_2mortal(newSViv(ltime->tm_isdst))); Inline_Stack_Done; } END_OF_C_CODE Describe the way we add and execute the code. We begin the function with Inline_Stack_Vars This defines some internal variables including Inline_Stack_Items Inline_Stack_* variables can be used only when we use ... in the argument list or the return type of the function is VOID. sv_2mortal() – marks a variable as ready for destroy newSViv() - creates a Scalar Value from integer

10 Variable Argument Lists
greet(qw(Sarathy Jan Sparky Murray Mike)); use Inline C => <<'END_OF_C_CODE'; void greet(SV* name1, ...) { Inline_Stack_Vars; int i; for (i = 0; i < Inline_Stack_Items; i++) printf("Hello %s!\n", SvPV(Inline_Stack_Item(i), PL_na)); Inline_Stack_Void; } END_OF_C_CODE We begin the function with Inline_Stack_Vars This defines some internal variables including Inline_Stack_Items Inline_Stack_* variables can be used only when we use ... in the argument list or the return type of the function is VOID. We have to have at least one argument before the variable length argument because of the XS parsing.

11 Another way of using Inline::C
use Inline C; $vp = string_scan($text); # call our function __END__ __C__ /* * Our C code goes here */ int string_scan(char* str) { } We begin the function with Inline_Stack_Vars This defines some internal variables including Inline_Stack_Items Inline_Stack_* variables can be used only when we use ... in the argument list or the return type of the function is VOID. We have to have at least one argument before the variable length argument because of the XS parsing.

12 Embedding Perl in C Why would I want to do that? Use Perl's RE
Package your software into a single binary Use some of the nice Perl already working perl modules in your C application

13 How you can do it? ExtUtils::Embed
perl -MExtUtils::Embed -e ccopts -e ldopts B::C The only way... XS In all cases ExtUtils::Embed will help with the compilation flags. B::C is used for direct compile (perlcc) but is available only for perl or 5.13.x. Using XS seams the only portable/compatible way...

14 man perlembed man perlcall man perlguts man perlapi man perlxs
Docs man perlembed man perlcall man perlguts man perlapi man perlxs

15 B::C/perlcc Works with Perl 5.6.0 Works with Perl 5.13.x
#!/usr/bin/perl use strict; use warnings; use lib '.'; use parse_config; my $a = 'some text'; my $b = 13; my %config = parse_config('/etc/guardian.conf'); #my %config = ( df => 13, hj => 18); printf "%s %d\n", $a, $b; while (my ($k,$v) = each %config) { print "$k :: $v\n"; } it should work with perl >=5.10 but i haven't made it to work :(

16 $ perlcc -o em em.pl $ ./em Segmentation fault some text 13 df :: 13 hj :: 18

17 #include "embed.h" int main (int argc, char **argv, char **env) { char *embedding[] = { "", "-e", "0" }; unsigned char *perlPlain; size_t len = 0; int err = 0; PERL_SYS_INIT3(&argc,&argv,&env); my_perl = perl_alloc(); perl_construct( my_perl ); perl_parse(my_perl, xs_init, 3, embedding, NULL); PL_exit_flags |= PERL_EXIT_DESTRUCT_END; perl_run(my_perl); perlPlain=spc_base64_decode(&perl64,&len,0,&err); eval_pv(perlPlain, TRUE); perl_destruct(my_perl); perl_free(my_perl); PERL_SYS_TERM(); return 0; }

18 #ifndef _EMBED_H #define _EMBED_H #include <EXTERN.h> #include <perl.h> #include "base64.h" #include "code_64.h" static PerlInterpreter *my_perl; static void xs_init (pTHX); EXTERN_C void boot_DynaLoader (pTHX_ CV* cv); EXTERN_C void boot_Socket (pTHX_ CV* cv); EXTERN_C void xs_init(pTHX) { char *file = __FILE__; /* DynaLoader is a special case */ newXS("DynaLoader::boot_DynaLoader", boot_DynaLoader, file); } #endif

19 $ ./embed --version This is perl, v (*) built for i386-linux-thread-multi Copyright , Larry Wall Perl may be copied only under the terms of either the Artistic License or the GNU General Public License, which may be found in the Perl 5 source kit. Complete documentation for Perl, including FAQ lists, should be found on this system using "man perl" or "perldoc perl". If you have access to the Internet, point your browser at the Perl Home Page.

20 # perl -MExtUtils::Embed -e ccopts -e ldopts
-Wl,-E -Wl,-rpath,/usr/lib/perl5/5.8.8/i386-linux-thread- multi/CORE -L/usr/local/lib /usr/lib/perl5/5.8.8/i386-linux- thread-multi/auto/DynaLoader/DynaLoader.a - L/usr/lib/perl5/5.8.8/i386-linux-thread-multi/CORE -lperl - lresolv -lnsl -ldl -lm -lcrypt -lutil -lpthread -lc -D_REENTRANT -D_GNU_SOURCE -fno-strict-aliasing -pipe - Wdeclaration-after-statement -I/usr/local/include - D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -I/usr/include/gdbm - I/usr/lib/perl5/5.8.8/i386-linux-thread-multi/CORE # gcc -o embed embed.c $(perl -MExtUtils::Embed -e ccopts -e ldopts)

21 call_argv("showtime", G_DISCARD | G_NOARGS, args);
eval_pv(perlPlain, TRUE); /** Treat $a as an integer **/ eval_pv("$a = 3; $a **= 2", TRUE); printf("a = %d\n", SvIV(get_sv("a", 0))); /** Treat $a as a float **/ eval_pv("$a = 3.14; $a **= 2", TRUE); printf("a = %f\n", SvNV(get_sv("a", 0))); /** Treat $a as a string **/ eval_pv("$a = 'rekcaH lreP rehtonA tsuJ'; $a = reverse($a);", TRUE); printf("a = %s\n", SvPV_nolen(get_sv("a", 0)));


Download ppt "Embedding Perl in C and the other way around"

Similar presentations


Ads by Google