• Save
C to perl binding
Upcoming SlideShare
Loading in...5
×
 

Like this? Share it with your network

Share

C to perl binding

on

  • 4,572 views

An overview about

An overview about

Statistics

Views

Total Views
4,572
Views on SlideShare
4,566
Embed Views
6

Actions

Likes
3
Downloads
0
Comments
0

2 Embeds 6

https://twitter.com 5
http://tweetedtimes.com 1

Accessibility

Categories

Upload Details

Uploaded via as Microsoft PowerPoint

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

C to perl binding Presentation Transcript

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