Your SlideShare is downloading. ×
0
C to perl binding
C to perl binding
C to perl binding
C to perl binding
C to perl binding
C to perl binding
C to perl binding
C to perl binding
C to perl binding
C to perl binding
C to perl binding
C to perl binding
C to perl binding
C to perl binding
C to perl binding
C to perl binding
C to perl binding
C to perl binding
C to perl binding
C to perl binding
C to perl binding
C to perl binding
C to perl binding
C to perl binding
C to perl binding
C to perl binding
C to perl binding
C to perl binding
C to perl binding
C to perl binding
C to perl binding
C to perl binding
C to perl binding
C to perl binding
C to perl binding
C to perl binding
C to perl binding
C to perl binding
C to perl binding
C to perl binding
C to perl binding
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×
Saving this for later? Get the SlideShare app to save on your phone or tablet. Read anywhere, anytime – even offline.
Text the download link to your phone
Standard text messaging rates apply

C to perl binding

4,024

Published on

An overview about

An overview about

Published in: Technology
0 Comments
3 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
4,024
On Slideshare
0
From Embeds
0
Number of Embeds
2
Actions
Shares
0
Downloads
0
Comments
0
Likes
3
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
No notes for slide

Transcript

  • 1. XS::TNG<br />The current status of Perl-C binding<br />ShmuelFomberg<br />YAPC Tokyo 2010<br />
  • 2. We have XS, don’t we?<br />XS is hard<br />Not true. The syntax is simple<br />XS is not hard<br />But when writing XS you are using:<br />XS syntax<br />Perl guts<br />Typesmaps<br />C<br />Learning all these in the same time, is hard<br />
  • 3. We are not going to talk about XS<br />XS is a known problem<br />A lot of documentation on the web<br />Most of it outdated or just wrong<br />We will talk about:<br />Ctypes– calling C libraries from Perl<br />Libperl++ - embedding and extending Perl using C++ library<br />XS++ - XS – C++ binding<br />
  • 4. Who am I<br />A Perl programmer from Israel<br />I’m here learning Japanese<br />Just started a three month course<br />My first YAPC talk<br />So, yoroshekoonegaishimasu<br />
  • 5. What is Ctypes?<br />Port from Python’s Ctypes<br />Good idea / interface<br />Still in making<br />Not on CPAN yet<br />Enable to call C functions inside DLLs, without making XS / intermediate DLL<br />
  • 6. Ctypes<br />Now let’s see some code:<br />use Ctypes;print chr CDLL->msvcrt->toupper({sig=>"cii"})->(ord("y"));# prints ‘Y’<br /># a more verbose style:my $func = Ctypes::Function->new<br /> ( { lib => 'msvcrt',<br /> name => 'toupper',<br /> argtypes => 'ii',<br /> restype => 'c' } );<br />print chr $func->(ord("y"));<br /># prints ‘Y’<br />
  • 7. Ctypes<br />Let’s see more:<br />my $func = WinDLL->user32-> MessageBoxA({sig=>"sipppI"});<br />$func->(0, "Hi", "BoxBox", 0);<br />
  • 8. Ctypes – built-in types<br />Signature details:<br />First char – call type. ‘s’ for stdcall, ‘c’ for cdecl.<br />Second char – return type<br />The rest - arguments <br />v => c_void,c => c_byte,C => c_char,s => c_short,S => c_ushort,i => c_int,I => c_uint,<br />l => c_long,L => c_ulong,f => c_float,d => c_double,D => c_longdouble,p => c_void_p,<br />
  • 9. Building types - Simple<br />my $array = Array( c_ushort, [ 1, 2, 3, 4, 5 ] );$array->[2] == 3;my $multi = Array( $array, $array2, $array3 ); # multidimensional <br />my $ushort = c_ushort(25);my $ushortp = Pointer($ushort);$$ushortp == $ushort;${$$ushortp} == 25; <br />
  • 10. Building types – Ad-hoc<br />my $struct = Struct([  f1 => c_char('P'),  f2 => c_int(10),  f3 => c_long(90000),]);<br />$struct->size == Ctypes::sizeof('c') + Ctypes::sizeof('i') + Ctypes::sizeof('l');$$struct->{f2} == 10;<br />my $alignedstruct = Struct({  fields => [   o1 => c_char('Q'),   o2 => c_int(20),   o3 => c_long(180000),  ],  align => 4,});<br />
  • 11. Building types – Callback<br />sub cb_func {  my( $ay, $bee ) = @_; return $ay <=> $bee;}<br />my $qsort = Ctypes::Function->new  ( { lib    => 'c', name   => 'qsort',   argtypes => 'piip‘, restype => 'v‘, } );<br />$cb = Ctypes::Callback->new( &cb_func, 'i', ‘ss');<br />my $disarray = Array(c_short , [2, 4, 5, 1, 3] );$qsort->($disarray, $#$disarray+1, Ctypes::sizeof('s'), $cb->ptr);$disarray->_update_;$disarray->[2] == 3<br />
  • 12. Ctypes – Libraries types<br />CDLL<br />Return type ‘i’, calling style ‘cdecl’<br />WinDLL<br />Return type ‘i’, calling style ‘stdcall’<br />OleDLL<br />Calling style “stdcall”<br />Return type HRESULT<br />Will throw exception automatically on error<br />
  • 13. Ctypes – Libraries types<br />PerlDLL<br />For calling Perl XS functions<br />provides XS environment for the called function<br />Checks the Perl error flag after the call<br />If there was an exception – re-throws<br />
  • 14. Libperl++<br />Extending and Embedding Perl<br />The goal: to let C++ do the hard work for you<br />Reference counting<br />Call stack operations<br />Type conversions<br />Exception conversions<br />http://github.com/Leont/libperl--<br />
  • 15. Libperl++ - Embedding<br />Let’s see some code:<br />Interpreter universe;universe.use("Carp", 1.000); bool success = universe.eval("print qq{Hello World }"); <br /># acessing / creating global variables <br />universe.scalar("status") = 404;<br />universe.hash("table").exists("hello"); <br /># creates @Module::data :<br />Array data = universe.array("Module::data"); <br />
  • 16. Libperl++ - Extending<br />Let’s say we have this C++ code:<br />class player { <br /> string get_name() const; <br /> pair<int, int> get_position() const; <br /> void set_position(pair<int, int>); <br /> double get_strength() const; <br /> void set_strength(double); <br /> void die(string); <br />}; <br />
  • 17. Libperl++ - Extending<br />It can be exported like this:<br />Class<player> player_class = universe.add_class("Player"); player_class.add("get_name", &player::get_name); player_class.add("get_position", &player::get_position); player_class.add("set_position", &player::set_position); player_class.add("get_strength", &player::get_strength); player_class.add("set_strength", &player::set_strength); player_class.add("die", &player::die); <br />The first line connects a C++ class “player” with <br />Perl class “Player”, then we add each method<br />
  • 18. Libperl++ - Extending<br />Of course, we can add a plain <br />(non-object) module<br />Package somewhere = universe.package("foo"); <br />somewhere.add("other_name", some_function); <br />
  • 19. Libperl++ - Extending<br />And the Perl side:<br />package Extend;<br />use strict;<br />use warnings;<br />use Exporter 5.57 qw/import/;<br />our @EXPORT_OK = qw/hello/;<br />use Perlpp::Extend;<br />1;<br />
  • 20. Libperl++ - Calling Perl<br />You really don’t want to know how much work is to call Perl function from C<br />Here is how to do it with Libperl++:<br />Ref<Code> some_function = universe.code("some_function"); <br />some_function("Hello World"); // in scalar context<br />some_function.list("Hello World"); // in list context<br />
  • 21. Libperl++ - Calling Perl<br />Also works for objects:<br />Ref<Any> testr = universe.package("Tester").call("new", 1);<br />testr.call("print");<br />testr.call("set", 3);<br />testr.call("print");<br />// automatically calls ‘DESTROY’ <br />
  • 22. Libperl++ - Scalars<br />Scalar value = universe.value_of(1);<br />value += 2;<br />// can use all normal operators: + - * / % == > < =<br />value = "1"; // the same as setting to 1<br />String value = universe.value_of("test");<br />value == std::string("test"); // convertible to/from std::string<br />value.replace(2, 2, value); // now contains ‘tetest’<br />value.insert(2, "st"); // now contains ‘testtest’<br />value = "test"; // simple assignment<br />
  • 23. Libperl++ - Arrays<br />first<br />max<br />min<br />shuffledsum<br />any<br />all<br />none<br />begin/end<br />rbegin/rend<br />push<br />pop<br />shift<br />unshift<br />reverse<br />remove<br />exists<br />length<br />clear<br />each<br />each_index<br />map<br />grep<br />reduce<br />Array bar = universe.list("a", "b");int length = bar.length();cout << "bla is " << baz[1] << endl; bar[4] = "e"; <br />void test(const Scalar::Base& val);<br />std::for_each(bar.begin(), bar.end(), test);<br />int converter(int arg);<br />Array singles = universe.list(1, 2, 3, 4); singles.map(converter).each(test); <br />
  • 24. Libperl++ - Hashs<br />insert<br />exists<br />erase<br />clear<br />length<br />each<br />keys<br />values<br />Hash map = universe.hash();<br />map["test"] = "duck";<br />map["foo" ] = "bar";<br />void printer(const char *key, <br /> const Scalar::Base& value); <br />map.each(printer);<br />
  • 25. Libperl++ - References<br />Any Perl variable support take_ref()<br />Ref<Scalar> value = universe.value_of(1).take_ref();<br />Reference can be specific or generic<br />Ref<Scalar>, Ref<Integer>, Ref<Number>, Ref<Any>, Ref<Hash><br />Reference tries to give operations shortcuts to the contained element<br />Ref<Hash> ref = hash.take_ref();<br />ref["foo"] = "rab";<br />is_object<br />isa<br />is_exactly<br />weaken<br />bless<br />get_classname<br />
  • 26. Libperl++ - custom type convertion<br />structmy_type {<br />int value;<br />my_type(int _value) : value(_value) {}<br />};namespace perl {<br /> namespace typecast {<br /> template<> structtypemap<my_type> {<br /> static my_typecast_to(const Scalar::Base& value) {<br /> return my_type(value.int_value());<br /> }<br />typedef boost::true_typefrom_type;<br /> static intcast_from(Interpreter&, const my_type& variable) {<br /> return variable.value;<br /> }<br /> };<br /> }<br />}<br />Signals that this type can be converted to Perl type<br />Can construct any Perl type, (using the interpreter) or any type convertible<br />
  • 27. ExtUtils::XSpp<br />XS does not handle objects<br />Only functions and constants<br />You can write the object binding yourself<br />Much fun<br />XS++ fills the gap<br />“transparent C++ objects in Perl”<br />
  • 28. ExtUtils::XSpp<br />It is still XS<br />So you need to know all the XS keywords, Perl internals and typemaps<br />Plus adds its own little language<br />Everything is translated back to XS for compilation<br />Module::Build::WithXSpp<br />See ExtUtils::XSpp’s example<br />
  • 29. XS++ - XSpp::Example.pm<br />package XSpp::Example; use strict; use warnings; <br />our $VERSION = '0.01'; <br />require XSLoader; XSLoader::load('XSpp::Example', $VERSION); <br />1; <br />
  • 30. XS++ - C++ headers<br />class Animal { public: Animal(const std::string& name); void SetName(const std::string& newName); std::string GetName() const; void MakeSound() const; <br />private: <br /> std::string fName; }; <br />class Dog : public Animal { <br />public: <br /> Dog(const std::string& name); <br /> void Bark() const; <br /> void MakeSound() const; <br />}; <br />
  • 31. XS++ - xsp file<br />#include "Animals.h" <br />%module{XSpp::Example}; <br />class Animal { <br /> %name{new} Animal(std::string& name); <br /> ~Animal(); <br /> void MakeSound(); <br /> void SetName(std::string& newName); <br /> std::string GetName(); <br />}; <br />class Dog : public Animal { <br /> %name{new} Dog(std::string& name); <br /> ~Dog(); <br /> void MakeSound(); <br /> void Bark(); <br />}; <br />
  • 32. XS++ - Dog.cc<br />#include "Animals.h"<br />Dog::Dog(const std::string& name) : Animal(name) {} <br />void Dog::Bark() const { <br />cout << "Woof" << endl; <br />} <br />void Dog::MakeSound() const { <br /> Bark(); <br />} <br />
  • 33. XS++ - Build.PL<br />#!/usr/bin/perl -w <br />use strict; <br />use Module::Build::WithXSpp; <br />my $build = Module::Build::WithXSpp->new( <br />module_name => 'XSpp::Example', <br /> license => 'perl', <br /> requires => {}, <br /> # Provides extra C typemaps for opaque objects: <br />extra_typemap_modules => { <br /> 'ExtUtils::Typemap::ObjectMap' => '0.01', <br /> }, <br />);<br />$build->create_build_script; <br />
  • 34. XS++ - mytype.map<br />Animal* O_OBJECT<br />Dog* O_OBJECT<br />std::string* T_STRINGPTR <br />std::string T_STRING <br />INPUT <br />T_STRING <br /> $var = std::string(SvPV_nolen($arg)) <br />T_STRINGPTR <br /> $var = new std::string(SvPV_nolen($arg)) <br />OUTPUT <br />T_STRING <br /> $arg = newSVpvn($var.c_str(), $var.length()); <br />T_STRINGPTR <br /> $arg = newSVpvn($var->c_str(), $var->length());<br />Declare these types as objects to export to Perl space<br />
  • 35. More about typemaps<br />ExtUtils::Typemap::Default<br />And the other modules in that distribution<br />
  • 36. Thank you<br />
  • 37. Building Libffi<br />Download from: http://github.com/atgreen/libffi<br />Target platform: Strawberry Perl 5.12<br />Needed tools: cygwin <br />with make, without gcc<br />To build:<br />copy src/x86/ffitarget.h to include/ffitarget.h<br />run bash<br />run configure<br />run make<br />It will produce binaries in the “.lib” directory:<br />Libffi.* => strewberryperl/c/lib<br />cygffi-5.dll => strewberryperl/c/bin<br />
  • 38. Building Ctypes<br />Download from: <br />http://gitorious.org/perl-ctypes<br />http://socghop.appspot.com/gsoc/student_project/show/google/gsoc2010/tpf/t127230763807<br />Make sure that cygwin is not available<br />perl Makefile.pl, dmake – test – install <br />
  • 39. Building Libperl++<br />You need C++ Boost<br />http://www.boost.org/<br />But only the headers<br />Libperl++ is a heavy C++ templates user<br />Using Module::Build style installer<br />perl Build.PL<br />perl Build<br />perl Build test <br />perl Build install <br />
  • 40. Building types - Point<br />package t_POINT;use strict;use warnings;use Ctypes;use Ctypes::Type::Struct;our @ISA = qw|Ctypes::Type::Struct|;our $_fields_ = [ ['x',c_int], ['y',c_int], ];<br />sub new { my $class = ref($_[0]) || $_[0]; shift; my $self = $class->SUPER::new({fields => $_fields_, values => [ @_ ] }); return bless $self => $class if $self;}<br />
  • 41. Building types - Point<br />my $point = new t_POINT( 30, 40 );$$point->{x} == 30;$$point->{y} == 40;$$point->[0] == 30;$$point->[1] == 40; <br /># yes, it is overloaded<br />my $point_2 = new t_POINT([ y => 30, x => 40 ]);my $point_3 = new t_POINT([ y => 50 ]);<br />

×