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,
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);
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(); };
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 ]);