Sure there are lots of ways to do this (as usually in Perl: "there's more than one way to do it"), just to name few:
- swig - result looks not native and clumsy, also you need to make facade-like interfaces for really complex classes
- ffi - also has problems with complex classes
- XS - official and wide-spread way. Btw smoothest and most seamless Win32::OLE module uses it exactly
and besides you can simple call perl functions directly from c++ code (with all bells and whistles "dSP; ENTER; SAVETMPS" etc) like polymake do
So this article is just remaining for myself how to bind small-sized c++ classes to perl using XS. Lets begin with simplest one - just perl wrapper around Interval-Tree
- to create new skeleton: h2xs -cfn Module::Name
- patch Makefile.PL to add XSOPT="-C++" and change C compiler CC="g++", also highly likely we should add -lstdc++ to LIBS
- don't forget to add all source/header files to MANIFEST
Code is simple, I prefer to make my own MAGIC instead of implementation DESTROY method - you will see further why
Next module is more complex bcs I want to have native tied arrays for stuff like sections/segments/symbols/relocs etc to make possible things likemy $e = Elf::Reader->new($ARGV[0]);
my $syms = $e->syms($sec);
foreach ( @$syms ) { ...
To achieve this we need to make our new magic. However there is problem - I have my own COM-like reference counting and want to have custom destructor in MAGIC table, so type PERL_MAGIC_tied
doesn't fit. On other hand method FETCHSIZE called from Perl_magic_sizepack which is PERL_MAGIC_tied->length
. Ok, we can implement our own length method for each magic table. Then magic tables sets up like:sv_magicext((SV*)AV_var, NULL, PERL_MAGIC_tied, &magic_vtab, (const char *)object, 0);
and we can implement only FETCH method for each iterator
Last module is wrapper around mips disassembler library - nothing special except it must be dynamically linked with described above native module. This is little bit tricky - we must pass several arguments to linker
- module name - bcs it don't starts with lib prefix we must use dirty hack: -l:module_name
- path to module for -L - you can extract it from Config as $Config{'sitearch'}
- and finally peek -Wl,--as-needed
Now my module can be loaded from perl. ldd shows:
linux-vdso.so.1 (0x00007ffec81db000)
Reader.so => /usr/local/lib/x86_64-linux-gnu/perl/5.30.0/auto/Elf/Reader/Reader.so (0x00007f2b9f036000)
libstdc++.so.6 => /usr/local/lib64/libstdc++.so.6 (0x00007f2b9ee0c000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f2b9ebfb000)
libgcc_s.so.1 => /usr/local/lib64/libgcc_s.so.1 (0x00007f2b9ebda000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f2b9ea8b000)
/lib64/ld-linux-x86-64.so.2 (0x00007f2b9f06a000)
As result of all this hard work I have mips disasm in perl with 100 lines of code
Комментариев нет:
Отправить комментарий