154x Filetype PDF File size 0.15 MB Source: www.swig.org
Perl Extension Building with SWIG David M. Beazley DavidFletcher DominiqueDumont Dept. of Computer Science Fusion MicroMedia, Corp. Hewlett Packard University of Chicago Longmont, CO 80501 LabTID Chicago, IL 60637 5AveRaymondChanas 38053Grenoblecedex 9 France Abstract providesgreater flexibility and often simplifies develop- ment since debugging and testing can be performed us- SWIG(Simplified Wrapper and Interface Generator) ing Perl scripts. Second, Perl can serve as a powerful is a freely available tool that integrates Perl, Python, user interface. In other words, rather than writing a user Tcl, and other scripting languages with programs writ- interface from scratch, it is possible to use a Perl inter- ten in C, C++, and Objective-C. This paper provides an preter instead. This also allows other for other possibil- introduction to SWIG and shows how it can be used to ities such as graphical user interface development with construct Perl extension modules. In addition, a num- Perl/Tk. Finally, Perl provides developers with a mech- ber of applications in which SWIG has been utilized are anism for assembling and controlling software compo- described. While SWIG is similar to other Perl exten- nents. Rather than creating a huge monolithic package, sion building tools such as xsubpp and h2xs, SWIG has C/C++ programscan be packaged as collections of Perl a number of unique features that help simplify the task extension modules. As a result, programs become more of creating Perl extension modules. Many of these fea- modular and easier to maintain. Furthermore, it is even tures are described as well as limitations and future di- possible to combineentirelydifferentprogramstogether rections. This paperis primarily intendedfordevelopers within a shared Perl interpreter. who are interested in combining Perl with applications This paper provides an introduction and overview of written in C or C++ as well as current SWIG users who SWIG,atooldesignedtointegrateCcodewithavariety are interested in learning more about some of SWIG’s of scripting languages including Perl, Python, and Tcl. advancedfeatures. Currently, SWIG can construct Perl extension modules on Unix and Windows-NTsystems. It also supports the ActiveStatePerlforWindowsandPerl4. SWIGhasbeen 1 Introduction freely available since February, 1996 and has been pre- viously described in Advanced Perl Programming, The One of Perl’s greatest strengths is its ability to sim- Perl Journal,andDr. Dobb’s Journal[1, 2, 3]. In ad- plify hard programming tasks as well as being able to dition, SWIG is packaged with a 300 page user manual solve the odd and varied computing problems that oc- describing its use [4]. The goal of this paper is not to cur on a day-to-day basis. While it would be nice to repeatall of this information,but to providean overview use Perl (or other high-level languages) for everything, of SWIG, demonstrate the use of some of its more ad- this is simply not practical for many applications. In vancedfeatures, and describe some of the ways that it is fact, performance critical tasks, low-level systems pro- currently being used. The authors include the developer gramming, and complex data structures are likely to be of SWIGandtwoofSWIG’sforemostPerlexpertswho implemented in a compiled language such as C or C++ havemadesubstantialcontributionsto SWIG’s develop- (and may be easier to manage in such languages). Fur- ment. thermore,developersoftenneedtoworkwithawideva- riety of existing applications and “legacy” systems that 2 PerlExtensionBuilding are written in such languages. The integration of Perl and code written in compiled languageshas a numberof practicalbenefits. First, it al- To interface Perl with code written in C or C++, it is lowsexistingC/C++applicationstobeincorporatedinto necessary to write wrappers that serve as a glue layer a high-level interpreted environment. This environment between the Perl interpreter and the underlying C code. These wrappers are responsible for converting data be- # file : Makefile.PL tween Perl and C, reporting errors, and other tasks. Perl use ExtUtils::MakeMaker; is packaged with several tools for creating these wrap- WriteMakefile( pers. One such tool is xsubpp, a compiler that takes ’NAME’ => ’Example’, interface definitionswritten in a special languageknown ’OBJECT’ => ’example.o fact.o’ as XS and converts them into wrappers. For example, ); supposethat you had the following C function: This script is then used to create a Makefile and module int fact(int n); as follows: Towrapthis function into a Perl module with xsubpp, unix > perl Makefile.PL youwouldwritethefollowingXSfile: unix > make /* file : example.xs */ unix > make install extern int fact(int n); Finally, in addition to creating the C componentof the MODULE = Example PACKAGE = Example extension module,it is necessary to write a .pm file that int is used to load and initialize the module. For example, fact(n) int n # file : Example.pm When processed with xsubpp, the following wrapper package Example; file is produced require Exporter; require DynaLoader; #include "EXTERN.h" @ISA = qw(Exporter DynaLoader); #include "perl.h" bootstrap Example; #include "XSUB.h" 1; extern int fact(int n); At this point, you should have a working Perl exten- XS(XS_Example_fact) sion module. In principle, building a Perl extension re- { quires an XS specification for every C function that is to dXSARGS; be accessed. To simplify the process of creating these if (items != 1) specifications, Perl includes h2xs, a tool that converts croak("Usage: Example::fact(n)"); Cheader files to XS descriptions. While useful, h2xs { is somewhat limited in its ability to handle global vari- int n = (int)SvIV(ST(0)); ables, structures, classes, andmoreadvancedC/C++fea- int RETVAL; tures. As a result, h2xs canbesomewhatdifficulttouse RETVAL = fact(n); ST(0) = sv_newmortal(); with more complexapplications. sv_setiv(ST(0), (IV)RETVAL); } XSRETURN(1); 3 SWIGOverview } XS(boot_Example) In a nutshell, SWIG is a specialized compiler that { transforms ANSI C/C++ declarations into scripting lan- dXSARGS; guage extension wrappers. While somewhat similar to char* file = __FILE__; h2xs,SWIGhasanumberofnotabledifferences. First, XS_VERSION_BOOTCHECK ; SWIGismuchless internals oriented than XS. In other newXS("Example::fact", words,SWIGinterfacescanusuallybeconstructedwith- XS_Example_fact, file); out any knowledge of Perl’s internal operation. Second, ST(0) = &sv_yes; SWIGisdesignedtobeextensibleand generalpurpose. XSRETURN(1); Currently, wrappers can be generated for Perl, Python, } Tcl, and Guile. In addition, experimental modules for To use the module, the wrapper code must be com- MATLABandJavahavebeendeveloped.Finally,SWIG piled and linked into a shared library that can be dynam- supports a larger subset of C and C++ including struc- ically loaded into the Perl interpreter. The easiest way to tures, classes, global variables, and inheritance. This dothis is with the MakeMaker utility by writing a script section provides a tour of SWIG and describes many of as follows: its interesting features. 3.1 ASmallTaste // File I/O (explained shortly) Asafirstexample,supposethatyouwantedtobuilda FILE *fopen(char *name, char *mode); 1 void fclose(FILE *); Perl interface to Thomas Boutell’s gd graphics library. Since gd is a C library, images are normally created by In this file, the ANSI C prototypes for every func- writing C code such as follows: tion that we would like to access from Perl are listed. #include "gd.h" In addition, a number of SWIG directives (which are int main() { always preceded by a “%”) appear. The %module di- gdImagePtr im; rective specifies the name of the extension module. The FILE *out; %f,%gblockisusedtoinsertliteral code into the out- int blk,wht; 2 put wrapper file. In this case, we simply include the /* Create an image */ “gd.h”headerfile. Finally,afewfileI/Ofunctionsalso im=gdImageCreate(200,200); appear. While not part of gd, these functions are needed to manufacturefilehandlesusedbyseveralgdfunctions. /* Allocate some colors */ TorunSWIG,thefollowingcommandisexecuted: b=gdImageColorAllocate(im,0,0,0); unix > swig -perl5 gd.i w=gdImageColorAllocate(im,255,255,255); Generating wrappers for Perl 5 /* Draw a line */ This produces two files, gd wrap.c and gd.pm.The gdImageLine(im,20,50,180,140,w); first file contains C wrapper functions that appear sim- /* Output the image */ ilar to the output that would have been generated by out=fopen("test.gif","wb"); xsubpp. The .pm file contains supporting Perl code gdImageGif(im,out); neededto load and use the module. fclose(out); Tobuild the module,the wrapper file is compiled and linked into a shared library. This process varies on every /* Clean up */ machine(consultthemanpages),butthefollowingsteps gdImageDestroy(im); are performed on Linux: } Bybuildinga Perl interface to gd, our goal is to write % gcc -fpic -c gd_wrap.c \ similar code in Perl. Thus, the functionality of the gd -Dbool=char \ library must be exposed to the Perl interpreter. To do -I/usr/lib/perl5/i586-linux/5.004/CORE this, a SWIG interface file can be written as follows: % gcc -shared gd_wrap.o -lgd -o gd.so // File : gd.i Atthispoint,themoduleisreadytouse. Forexample, %module gd the earlier C program can be directly translated into the %{ following Perl script: #include "gd.h" #!/usr/bin/perl %} use gd; typedef gdImage *gdImagePtr; # Create an image gdImagePtr gdImageCreate(int sx, int sy); $im = gd::gdImageCreate(200,200); void gdImageDestroy(gdImagePtr im); # Allocate some colors void gdImageLine(gdImagePtr im, $b=gd::gdImageColorAllocate($im,0,0,0); int x1, int y1, $w=gd::gdImageColorAllocate($im,255, int x2, int y2, 255,255); int color); int gdImageColorAllocate(gdImagePtr im, # Draw a line int r, int g, int b); gd::gdImageLine($im,20,50,180,140,$w); void gdImageGif(gdImagePtr im, FILE *o); 1gdis a freely available graphics library for producing GIF images # Output the image and can be obtained at www.boutell.com/gd/gd.html.APerl $out=gd::fopen("test.gif","wb"); module to gd, developed by Lincoln Stein, is also available on CPAN gd::gdImageGif($im,$out); so interested readers are encouraged to compare the results of using SWIGagainst an existing Perl extension. 2This syntax is derived from lex and yacc. gd::fclose($out); 3.3 DataModel # Clean up The most critical part of interfacing Perl to C pro- gd::gdImageDestroy($im); grams is the management of data. Since Perl and C uti- 3.2 InputFiles lize a different set of internal datatypes, wrapper gener- ators are responsible for producing code that marshals Inthegdexample,SWIGwasgivenaspecialinterface data and objects between languages. For fundamental file containing a list of the C declarations to be included types such as int and double the conversion pro- inthePerlmodule. WhenworkingwithalargeClibrary, cess is straightforward. However,pointers, arrays, struc- interface files can often be constructed by copying an tures, and objects complicate the process. Furthermore, existing header file and modifying it slightly. However, since most C/C++ programsmakeextensiveuseofthese in some cases, it is possible to include a header file as datatypes, it is important for wrapper generators to sup- follows: port as many of these datatypes as possible. %module 3.3.1 Pointers %{ #include "gd.h" SWIG maps C pointers and C++ references into Perl %} blessed references. These references contain both the // Grab the declarations from gd.h value of the pointer itself, plus a type-signature. In the %include "gd.h" gd example, pointers were used to manage both images and files. If one were to print out the value a pointer, it // Some file I/O functions wouldappearasfollows: FILE *fopen(char *name, char *mode); gdImagePtr=SCALAR(0x80b9914) void fclose(FILE *); The%includedirectivetellsSWIGtoincludeafile SWIG uses the type-signature to perform run-time and parse all of the declarations it contains. In this case, checking of all pointer values. These checks emulate the interface would now wrap every function in the gd manyofthe checks that would have been performed by library as opposed to the half-dozen functions listed in a C compiler. When an invalid Perl datatype or pointer the first example. of invalid type is used, a run-time error is generated. For SWIGalsoincludesaCpreprocessorthatcanbeused example, for macro expansion and conditional compilation. If a % perl new application is being written with SWIG in mind, use gd; header files can be written as follows: $f = gd::fopen("test.gif","w"); #ifdef SWIG gd::gdImageLine($f,20,50,180,140,0); %module gd Type error in argument 1 of gdImageLine. %{ Expected gdImagePtr. at - line 3. #include "gd.h" Type-checkingisbasedonthenameofeachdatatype. %} However, the type-checker also keeps track of C++ in- #endif heritance hierarchies and typedef definitions. Thus, /* C declarations */ an acceptable pointer type includes any alternate names ... that might have been created with a typedef declara- Withthisapproach,thefilecanserveasbothavalidC tion as well as any derived datatypes in C++. header file and as an interface specification. The SWIG When pointers are manipulated in Perl, they are symbolisonlydefinedwhenSWIGisparsingsospecial opaque values. That is, pointers can be created and directives can be easily hidden from the C compiler as passed around to other C functions, but they can not needed. be dereferenced directly. Thus, in the example, it is Finally, for the truly lazy, SWIG can sometimes be difficult (or impractical) for a user to directly manip- run directly on C header and source files. For example, ulate the internal representation of an image from the % swig -perl5 -module gd gd.h Perl interpreter. Furthermore, SWIG, by default, han- % swig -perl5 -module example example.c dles all pointers in a uniform manner. Thus, datatypes such as FILE * are represented as blessed references Most users, however, use a mix of dedicated interface even though such types may appear remarkably similar files and header files. to other Perl datatypes such as file handles.
no reviews yet
Please Login to review.