home *** CD-ROM | disk | FTP | other *** search
/ PC Professionell 2004 December / PCpro_2004_12.ISO / files / webserver / tsw / TSW_3.4.0.exe / Apache2 / perl / xsbuilder.osc2002.pod < prev    next >
Encoding:
Text File  |  2002-08-05  |  17.4 KB  |  645 lines

  1.  
  2.  
  3. =head1 XSBuilder - Autogenerating XS-glue Code
  4.  
  5.  
  6. O'Reilly OpenSource Convention 2002 
  7.  
  8. Gerald Richter
  9.  
  10. ecos gmbh  
  11.  
  12. http://www.ecos.de
  13.  
  14. =head1 XSBuilder - What is it?
  15.  
  16.  
  17. =head2 It's purpose is to automaticly generate a Perl interface to C Code
  18.  
  19. =head2 Solves the problem, that the Perl interface is not always uptodate with the C interface
  20.  
  21. =head2 Saves a lot of Copy&Paste work
  22.  
  23. =head2 Systematical changes have to be done only once
  24.  
  25. For example changes in the memory management of strings.
  26.  
  27. =head2 Is part of mod_perl 2.0 build system
  28.  
  29. Most code is developed by Doug MacEachern. Additionaly I have 
  30.  
  31. =over
  32.  
  33. =item abstracted the code from mod_perl so it's useable for any C code
  34.  
  35. =item added new features like callbacks and the ability to parse comments
  36.  
  37. =item Replaced C::Scan with a Parse::RecDescent to be platform and compiler independend
  38.  
  39. =back
  40.  
  41. Goal is to replace the current mod_perl XS generation code with XSBuilder
  42.  
  43. =head2 Inline versus XSBuilder
  44.  
  45. =over
  46.  
  47. =item Inline: embed C-Code into Perl
  48.  
  49. =item XSBuilder: Create interface for existing C-libraries/applicationen
  50.  
  51. =back
  52.  
  53. =head1 XSBuilder - What does it do?
  54.  
  55. =head2 Create Perl functions/methods for every C function
  56.  
  57. The function can be assigned to different packages, also automaticly
  58. by inspecting the first parameter
  59.  
  60. =head2 Create a Perl class for every C structure
  61.  
  62. Every element of structure becomes a Perl method to get/set it's value.
  63. The object can be either a scalar reference (used by mod_perl) or
  64. a reference to a hash (use by Embperl), which allows to store extra 
  65. data by the Perl code into this hash.
  66.  
  67. =head2 Create glue code to handle callbacks
  68.  
  69. There several sorts of callback, not all are implemented right now
  70.  
  71. =head2 Create Perl constant subs
  72.  
  73. Coming soon...
  74.  
  75. =head1 XSBuilder - How does it work?
  76.  
  77. =head2 Parse the C header files
  78.  
  79. Extract
  80.  
  81. =over
  82.  
  83. =item Functions, their arguments and return types
  84.  
  85. =item Structures and it's members
  86.  
  87. =item Constants
  88.  
  89. =item Callbacks
  90.  
  91. =back
  92.  
  93. and create four tables which contains the results
  94.  
  95. =head2 Create the XS code
  96.  
  97. Input is
  98.  
  99. =over
  100.  
  101. =item The source tables
  102.  
  103. =item Mapfiles which contains the mapping from C to Perl
  104.  
  105. =item Addtional C and Perl code that can be used to customize the interface
  106.  
  107. =back
  108.  
  109. Output is
  110.  
  111. =over
  112.  
  113. =item The XS files (one form every generated class)
  114.  
  115. =item Makefile.PL for every class
  116.  
  117. =item pm files
  118.  
  119. =back
  120.  
  121.  
  122.  
  123.  
  124. =head1 Parse the source
  125.  
  126. =head2 Create your own ParseSource class and override methods...
  127.  
  128.     package Apache::DAV::ParseSource;
  129.  
  130.     use strict;
  131.     use vars qw{@ISA $VERSION} ;
  132.     use ExtUtils::XSBuilder::ParseSource  ;
  133.  
  134.     @ISA = ('ExtUtils::XSBuilder::ParseSource') ;
  135.     $VERSION = '0.01';
  136.  
  137.     my $dav_dir = 'C:\perl\msrc\cvs\mod_dav' ;
  138.     my $ap_dir  = 'c:\programme\apache group\apache' ;
  139.  
  140.     # ============================================================================
  141.     sub find_includes {
  142.         my $self = shift;
  143.         return $self->{includes} if $self->{includes};
  144.         my @includes = ("$ap_dir/include/ap_alloc.h", "$dav_dir/mod_dav.h") ;
  145.         return $self->{includes} = $self -> sort_includes (\@includes) ;
  146.         }
  147.  
  148.     # ============================================================================
  149.     sub package     { 'Apache::DAV' } 
  150.  
  151.     # ============================================================================
  152.     sub preprocess {
  153.         my $self     = shift ;
  154.         $_[0] =~ s/(?:API_EXPORT)(?:_NONSTD)?\s*\(\s*(.*?)\s*\)/$1/g ;
  155.     }
  156.  
  157.  
  158.     1;
  159.  
  160. =head2 ...run it
  161.  
  162.     use FindBin ;
  163.     use lib ($FindBin::Bin) ;
  164.  
  165.     require ParseSource ; 
  166.  
  167.     Apache::DAV::ParseSource -> run ;
  168.  
  169. =head2 ...and you get
  170.  
  171.     C:\perl\msrc\davint>perl xsbuilder\source_scan.pl
  172.     Will use mod_dav in C:\perl\msrc\cvs\mod_dav
  173.     Will use Apache in c:\programme\apache group\apache
  174.     Initialize parser
  175.     scan c:\programme\apache group\apache/include/ap_alloc.h ...
  176.     constant: APACHE_ALLOC_H
  177.     func:     ap_init_alloc
  178.     func:     ap_cleanup_alloc
  179.     func:     ap_make_sub_pool
  180.     func:     ap_destroy_pool
  181.     constant: ap_pool_join
  182.     func:     ap_pool_join
  183.     func:     ap_find_pool
  184.     func:     ap_pool_is_ancestor
  185.     func:     ap_clear_pool
  186.     func:     ap_cleanup_for_exec
  187.     func:     ap_palloc
  188.     func:     ap_pcalloc
  189.     func:     ap_pstrdup
  190.     func:     ap_pstrndup
  191.     func:     ap_pstrcat
  192.     func:     ap_pvsprintf
  193.       valuefield: ap_pool * : pool
  194.       valuefield: int : elt_size
  195.       valuefield: int : nelts
  196.       valuefield: int : nalloc
  197.       valuefield: char * : elts
  198.     struct:    (type=array_header)
  199.     ...
  200.  
  201. =head2 The result is stored in four tables
  202.  
  203. =over
  204.  
  205. =item xsbuilder/tables/Apache/DAV/FuntionTable.pm
  206.  
  207. Contains all function, it arguments and comments
  208.  
  209. =item xsbuilder/tables/Apache/DAV/ConstantTable.pm
  210.  
  211. Contains all constants
  212.  
  213. =item xsbuilder/tables/Apache/DAV/StructureTable.pm
  214.  
  215. Contains all structures, it's members and their comments
  216.  
  217. =item xsbuilder/tables/Apache/DAV/CallbackTable.pm
  218.  
  219. Contains all callback function definitions
  220.  
  221. =back
  222.  
  223. =head1 Create the map files
  224.  
  225. =head2 Mapfiles are used to tell XSBuilder how C datatypes, structures
  226. and function aruments should be mapped into Perl ones.
  227.  
  228. =head2 Create your own WrapXS class and override methods
  229.  
  230.     package Apache::DAV::WrapXS ;
  231.     use strict;
  232.     use vars qw{@ISA $VERSION} ;
  233.  
  234.     use ExtUtils::XSBuilder::WrapXS ;
  235.  
  236.     @ISA = ('ExtUtils::XSBuilder::WrapXS') ;
  237.     $VERSION = '0.01';
  238.  
  239.     # ============================================================================
  240.     sub new_parsesource  { [ Apache::DAV::ParseSource->new ] }
  241.  
  242.     # ============================================================================
  243.     sub my_xs_prefix  { 'davxs_' }
  244.  
  245.     # ============================================================================
  246.     sub h_filename_prefix  { 'moddav_xs_' }
  247.  
  248.     # ============================================================================
  249.     sub xs_includes {
  250.         my $self = shift ;
  251.         my $i = $self -> SUPER::xs_includes ;
  252.         my @i = grep (!/ap_alloc/, @$i) ;
  253.         return \@i ;
  254.     }
  255.  
  256.  
  257. =head2 XSBuilder can create/update initial maps for you
  258.  
  259.     use FindBin ;
  260.     use lib ($FindBin::Bin) ;
  261.  
  262.     require ParseSource ; 
  263.     require WrapXS ; 
  264.  
  265.     Apache::DAV::WrapXS->checkmaps (' ');
  266.  
  267. =head2 run it
  268.  
  269.     C:\perl\msrc\davint>perl xsbuilder\xs_check.pl
  270.     Will use mod_dav in C:\perl\msrc\cvs\mod_dav
  271.     Will use Apache in c:\programme\apache group\apache
  272.     Parse xsbuilder\maps/_types.map...
  273.     WARNING: No *_function.map file found in xsbuilder\maps
  274.     WARNING: No *_callback.map file found in xsbuilder\maps
  275.     WARNING: No *_structure.map file found in xsbuilder\maps
  276.     Write xsbuilder\maps/new_function.map...
  277.     Write xsbuilder\maps/new_callback.map...
  278.     Write xsbuilder\maps/new_structure.map...
  279.     Write xsbuilder\maps/new_type.map...
  280.  
  281. =head2 Now we have four map files
  282.  
  283.  
  284. =over 4
  285.  
  286. =item new_types.map
  287.  
  288. Contains the mapping from C type to Perl classes
  289.  
  290. =item new_functions.map
  291.  
  292. Contains the mapping form C functions to Perl functions. Can be used to 
  293. reorder arguments, tell XSBuilder which arguments are actualy return values 
  294. and in which Perl package the function will be created.
  295.  
  296. =item new_structures.map
  297.  
  298. Contains the mapping from C structures to Perl classes and defines for which
  299. members a access methods should be created. You can also specify if you want a
  300. C<new> method for the class.
  301.  
  302. =item new_callbacks.map
  303.  
  304. Contains the mapping form C callback functions to Perl callback functions. Can be used to 
  305. reorder arguments, tell XSBuilder which arguments are actualy return values 
  306. and in which Perl package the function will be created.
  307.  
  308. =back
  309.  
  310. It's a good idea to rename the prefix from C<new_> to something unique, here we use C<dav>
  311.  
  312. Everytime you rerun checkmaps, XSBuilder will create new_* files with the items
  313. that are not already part of the other maps.
  314.  
  315. =head2 Next step is to customize the maps...
  316.  
  317. =head1 type map
  318.  
  319. =head2 autogenerated dav_type.map
  320.  
  321.     DIR    |
  322.     FILE    |
  323.     HANDLE    |
  324.     array_header    |
  325.     dav_buffer    |
  326.     dav_dyn_context    |
  327.     dav_dyn_hooks    |
  328.     dav_dyn_module    |
  329.     dav_dyn_provider    |
  330.     dav_error    |
  331.     dav_get_props_result    |
  332.     dav_hooks_liveprop    |
  333.     dav_hooks_locks    |
  334.     dav_hooks_repository    |
  335.     dav_if_header    |
  336.     dav_if_state_type    |
  337.     ...
  338.  
  339. =head2 Add Perl classes
  340.  
  341.     struct array_header         | Apache::Array
  342.     struct dav_buffer           |
  343.     struct dav_datum            | Apache::DAV::Datum
  344.     struct dav_dyn_context      | Apache::DAV::DynContext
  345.     struct dav_dyn_hooks        | Apache::DAV::DynHooks
  346.     struct dav_dyn_module       | Apache::DAV::DynModule
  347.     struct dav_dyn_provider     | Apache::DAV::DynProvider
  348.     struct dav_error            | Apache::DAV::Error
  349.     struct dav_get_props_result | Apache::DAV::PropsResult
  350.     struct dav_hooks_db         | Apache::DAV::HooksDb
  351.     struct dav_hooks_liveprop   | Apache::DAV::HooksLiveprop
  352.     struct dav_hooks_locks      | Apache::DAV::HooksLocks
  353.     struct dav_hooks_repository | Apache::DAV::HooksRepository
  354.     struct dav_hooks_vsn        | 
  355.     struct dav_if_header        | Apache::DAV::IfHeader
  356.     struct dav_if_state_list    | Apache::DAV::StateList
  357.     ...
  358.     struct pool                 | Apache::Pool
  359.     struct request_rec          | Apache::
  360.     struct server_rec           | Apache::Server
  361.     ...
  362.  
  363. Defines the mapping from C datatypes to Perl datatypes and classes
  364. and tells XSBuilder which datatype are (like) structures
  365.  
  366. =head1 function map
  367.  
  368. Function map defines the mapping from C functions arguments to Perl arguments
  369.  
  370. =over 
  371.  
  372. =item Tell XSBuilder where to place functions and which prefix to strip
  373.  
  374.     MODULE=Apache::DAV   PACKAGE=guess    PREFIX=dav_
  375.  
  376. =item Simple entries in the function map will be mapped 1:1 from C to Perl
  377.  
  378.      dav_add_response
  379.      dav_buffer_append
  380.      dav_buffer_init
  381.      dav_buffer_place
  382.      dav_buffer_place_mem
  383.      dav_check_bufsize
  384.      dav_close_propdb
  385.      dav_collect_liveprop_uris
  386.      dav_dyn_module_add
  387.      dav_empty_elem
  388.     ...
  389.  
  390. =item The following map file entry tells XSBuilder that the value of C<res_p> should be returned
  391.  
  392.      dav_get_resource        | | r, <res_p
  393.  
  394. The C function
  395.  
  396.     int dav_get_resource(request_rec *r, dav_resource **res_p) ;
  397.  
  398. How to call it from Perl
  399.  
  400.     # get a sub request of the actual document
  401.     $subr = $r -> lookup_uri($uri);
  402.  
  403.     # get a mod_dav resource object
  404.     my ($err, $resource) =  $subr->get_resource;
  405.  
  406. =item You can let XSBuilder insert your custom code, for the interface 
  407.  
  408. If you call C<get_props> from Perl C<glue_dav_get_props> will be called, which can adjust
  409. the arguments and return types as necessary. The actual code for C<glue_dav_get_props> 
  410. will be taken from separate include file.
  411.  
  412.      dav_get_props     | glue_
  413.      dav_get_allprops    | glue_
  414.  
  415.  
  416. xsinclude\Apache\DAV\PropResult\Apache__DAV__PropResults.h
  417.  
  418.     dav_get_props_result * dav_glue_get_props(dav_propdb * db, dav_xml_doc *doc)
  419.         {
  420.         dav_get_props_result * result = (dav_get_props_result *)ap_palloc (db -> p, sizeof (dav_get_props_result)) ;
  421.         *result = dav_get_props(db, doc) ;
  422.         return result ;
  423.         }
  424.  
  425.  
  426. =item Arguments can be replaced
  427.  
  428.     MODULE=Apache::Array   PACKAGE=Apache::Array PREFIX=ap_
  429.  
  430.      ap_make_array      | ap_make_array(r->pool, nelts, elt_size) | request_rec *:r, nelts, elt_size
  431.  
  432. ap_make_array requires a pool a it's first parameter, we pass the request_rec from Perl and
  433. XSBuilder will take the pool from the request_rec.
  434.  
  435. =back
  436.  
  437.  
  438. =head1 structure map
  439.  
  440.  
  441.      MALLOC=strdup:$dest = ($type)strdup($src)
  442.      FREE=strdup:free($src)
  443.  
  444.      <dav_xml_elem>
  445.        name
  446.        ns
  447.        lang
  448.        first_cdata
  449.        following_cdata
  450.        parent
  451.        next
  452.        first_child
  453.        attr
  454.        last_child
  455.        ns_scope
  456.        propid
  457.        provider
  458.        ns_map
  459.        new
  460.      </dav_xml_elem>
  461.  
  462.      MALLOC=strdup:$dest = ($type)ap_pstrdup(obj -> pool, $src)
  463.  
  464.      <array_header>
  465.        pool
  466.        elt_size
  467.        nelts
  468.        nalloc
  469.        elts
  470.        private
  471.      </array_header>
  472.  
  473. =head2 Create a accessor functions for every element and, if requested, a new method
  474.  
  475.         $setprop = Apache::DAV::XMLElem -> new ({name => 'prop'}) ;
  476.         $elem    = Apache::DAV::XMLElem -> new ({name => $name, ns => $namespaces}) ; 
  477.         $setprop -> first_child($elem) ;
  478.         $first = $setprop -> first_child ;
  479.  
  480. =head2 some datatypes, like strings, requires dynamic allocated memory
  481.  
  482.  
  483. From _types.map,which conatins a set of standard types
  484.  
  485.     int             | IV
  486.     int *           | UNDEFINED
  487.     unsigned int    | UV
  488.     signed int      | IV
  489.     long            | IV
  490.     long int        | IV
  491.     unsigned long   | UV
  492.     unsigned        | UV
  493.  
  494.     char *                   | PV           | | | strdup
  495.     const char *             | PV           | | | strdup
  496.     const char **            | UNDEFINED    
  497.     char const *             | PV           | | | strdup
  498.     unsigned char *          | PV           | | | strdup
  499.     const unsigned char *    | PV           | | | strdup
  500.     ...
  501.  
  502. =head1 callback maps
  503.  
  504. Callback maps have the same options a function maps
  505.  
  506.     # dav_hooks_db -> open
  507.      
  508.      dav_error *(*)(pool * p,const dav_resource * resource,int ro,dav_db * * pdb)  | p, resource, ro=0, <pdb 
  509.     
  510.     
  511.     # dav_hooks_lock -> has_locks
  512.     
  513.      dav_error *(*)(dav_lockdb * lockdb,const dav_resource * resource,int * locks_present)
  514.  
  515.  
  516. =head1 Generate the XS files
  517.  
  518.     use FindBin ;
  519.     use lib ($FindBin::Bin) ;
  520.  
  521.     require ParseSource ; 
  522.     require WrapXS ; 
  523.  
  524.     Apache::DAV::WrapXS->run;
  525.  
  526. =head2 ...and run...
  527.  
  528.     C:\perl\msrc\davint>perl xsbuilder\xs_generate.pl
  529.     Will use mod_dav in C:\perl\msrc\cvs\mod_dav
  530.     Will use Apache in c:\programme\apache group\apache
  531.     Parse xsbuilder\maps/_types.map...
  532.     Parse xsbuilder\maps/dav_type.map...
  533.     mkdir xs
  534.     writing...xs//typemap
  535.     Parse xsbuilder\maps/dav_functions.map...
  536.     WARNING: Cannot map type int(*)(void * ,const char * ,const char * ) for function ap_table_do
  537.     WARNING: Cannot map type dav_buffer * for function dav_buffer_append
  538.     WARNING: Cannot map type dav_buffer * for function dav_buffer_init
  539.     WARNING: Cannot map type dav_buffer * for function dav_buffer_place
  540.     WARNING: Cannot map type dav_buffer * for function dav_buffer_place_mem
  541.     WARNING: Cannot map type dav_buffer * for function dav_check_bufsize
  542.     WARNING: Cannot map return type int * for function dav_collect_liveprop_uris
  543.     WARNING: Cannot map type dav_resource * * for function dav_ensure_resource_writable
  544.     WARNING: Cannot map type dav_buffer * for function dav_lock_get_activelock
  545.     WARNING: Cannot map type dav_buffer * for function dav_set_bufsize
  546.     WARNING: Cannot map type int * for function dav_xml2text
  547.     struct array_header...
  548.     Parse xsbuilder\maps/dav_structure.map...
  549.          elt_size...
  550.          nelts...
  551.          nalloc...
  552.          elts...
  553.     struct dav_buffer...
  554.     struct dav_datum...
  555.          dptr...
  556.          dsize...
  557.     struct dav_dyn_context...
  558.  
  559. =head1 Makefile.PL
  560.  
  561. =head2 We need create a top level Makefile.PL
  562.  
  563.     use ExtUtils::MakeMaker ();
  564.     
  565.     my $apdir  = '/path/to/apache';
  566.     my $davdir = '/path/to/moddav';
  567.  
  568.     %MMARGS = (
  569.            'INC'    => "-I\"$davdir\" -I\"$apdir/include\" -I\"$apdir/os/unix\" -I\"$dir/xs\"  -I\"$dir/xsinclude\"",
  570.            ) ;
  571.  
  572.  
  573.     open FH, ">xs/mmargs.pl" or die "Cannot open xs/mmargs.pl ($!)" ;
  574.     print FH Data::Dumper -> Dump ([\%MMARGS], ['MMARGS']) ;
  575.     close FH ;
  576.  
  577.  
  578.     ExtUtils::MakeMaker::WriteMakefile(
  579.         'NAME'    => 'Apache::DAV',
  580.         'VERSION' => '0.13',
  581.         %MMARGS,
  582.     );
  583.  
  584.  
  585. =head2 Makefile.PL's for all class are generated automaticly
  586.  
  587.     C:\perl\msrc\davint>perl Makefile.PL
  588.     Will use Apache in c:\programme\apache group\apache
  589.     Will use mod_dav in C:\perl\msrc\cvs\mod_dav
  590.     Checking if your kit is complete...
  591.     Looks good
  592.     Writing Makefile for Apache::Array
  593.     Writing Makefile for Apache::DAV::Datum
  594.     Writing Makefile for Apache::DAV::DynContext
  595.     Writing Makefile for Apache::DAV::DynHooks
  596.     Writing Makefile for Apache::DAV::DynModule
  597.     Writing Makefile for Apache::DAV::DynProvider
  598.     Writing Makefile for Apache::DAV::Error
  599.     Writing Makefile for Apache::DAV::HooksDb
  600.     Writing Makefile for Apache::DAV::HooksLiveprop
  601.     Writing Makefile for Apache::DAV::HooksLocks
  602.     Writing Makefile for Apache::DAV::HooksRepository
  603.     Writing Makefile for Apache::DAV::IfHeader
  604.     Writing Makefile for Apache::DAV::Lock
  605.     Writing Makefile for Apache::DAV::LockDB
  606.     Writing Makefile for Apache::DAV::LockTokenList
  607.     Writing Makefile for Apache::DAV::LockupResult
  608.     Writing Makefile for Apache::DAV::PropCtx
  609.     Writing Makefile for Apache::DAV::PropsResult
  610.     Writing Makefile for Apache::DAV::Resource
  611.     Writing Makefile for Apache::DAV::Response
  612.     Writing Makefile for Apache::DAV::StateList
  613.     Writing Makefile for Apache::DAV::Text
  614.     Writing Makefile for Apache::DAV::TextHeader
  615.     Writing Makefile for Apache::DAV::WalkerCtx
  616.     Writing Makefile for Apache::DAV::XMLAttr
  617.     Writing Makefile for Apache::DAV::XMLDoc
  618.     Writing Makefile for Apache::DAV::XMLElem
  619.     Writing Makefile for Apache::DAV
  620.     Writing Makefile for Apache::TableEntry
  621.     Writing Makefile for Apache
  622.     Writing Makefile for WrapXS
  623.     Writing Makefile for Apache::DAV
  624.  
  625. =head2 and now compile...
  626.  
  627. =head1 How does it go on...
  628.  
  629. =head2 Generating documentation
  630.  
  631. XSBuilder already extracts source comments for functions and structures. 
  632. It also parses doxygen comments, which are used in Apache 2.0.
  633. Lyle Brooks has started on automaticly createing POD files from this information.
  634.  
  635. =head2 Improving callbacks
  636.  
  637. Callbacks are the main area that needs improvement.
  638.  
  639. =head2 Bring it back to mod_perl 2.0
  640.  
  641. =head2 First version will be released just after the conference to CPAN
  642.  
  643. =head2 Any feedback and help appreciated
  644.  
  645. =head2 Questions?