juda has asked for the wisdom of the Perl Monks concerning the following question:

Hi. My question concerns how one defines in XS that one has a C++ class. The only docs I can find on the subject of using XS with C++ is in the XS reference manual so I am trying to run their example but it is failing on "make" and the error indicates that the compiler is not recognizing the language as C++, so it doesn't recognize the class. This would make sense since it is compiling a .c file, namely myclass.c. I am confused. No matter what I do, it seems that xsubpp generates a .c file and never a .cc file. But if this is the case, then how will it ever recognize class declarations? Or is it saying that I have not supplied a class definition? What am I missing? Here's the output of "make":
cc -c -O -DVERSION=\"0.01\" -DXS_VERSION=\"0.01\" -Kpic -I/usr/ +local/lib/ perl5/sun4-solaris/5.00405/CORE myclass.c "/home/judyf/perlwork/myclass/myclass.h", line 9: undefined or not a t +ype: class "/home/judyf/perlwork/myclass/myclass.h", line 9: syntax error before +or at: col or "/home/judyf/perlwork/myclass/myclass.h", line 9: undefined or not a t +ype: color "/home/judyf/perlwork/myclass/myclass.h", line 15: syntax error before + or at: / "/home/judyf/perlwork/myclass/myclass.h", line 23: syntax error before + or at: in t "/home/judyf/perlwork/myclass/myclass.h", line 24: cannot recover from + previous errors cc: acomp failed for myclass.c *** Error code 2 make: Fatal error: Command failed for target `myclass.o'
Here's the class declaration from the myclass.h file:
class color { public: color(); ~color(); int blue(); int set_blue( int ); private: int c_blue; };
Here's the relevant .xs code:
int color::blue() void color::set_blue( val ) int val
My instinct would be, in the myclass.xs file, to create a new package within the one module (called "color") but based on the reference manual doc, I refrained from doing this and kept the class method declaration under the one package (with same name as module). hence, in myclass.xs:
MODULE = myclass PACKAGE = myclass
Here's the relevant portion of typemap file:
color * O_OBJECT OUTPUT # The Perl object is blessed into 'CLASS', which should be a # char* having the name of the package for the blessing. O_OBJECT sv_setref_pv( $arg, CLASS, (void*)$var ); INPUT O_OBJECT if( sv_isobject($arg) && (SvTYPE(SvRV($arg)) == SVt_PVMG) ) $var = ($type)SvIV((SV*)SvRV( $arg )); else{ warn( \"${Package}::$func_name() -- $var is not a bles +sed SV ref erence\" ); XSRETURN_UNDEF; }
Here's Makefile.PL (where I set 'XSOPT' to tell it I'm using C++):
use ExtUtils::MakeMaker; WriteMakefile( 'NAME' => 'myclass', 'VERSION_FROM' => 'myclass.pm', # finds $VERSION 'LIBS' => [''], # e.g., '-lm' 'DEFINE' => '', # e.g., '-DHAVE_SOMETHING' 'INC' => '', # e.g., '-I/usr/include/other' 'XSOPT' => '-C++', );
Thanks for your help.

Replies are listed 'Best First'.
Re: using XS with C++
by qi3ber (Scribe) on Jul 21, 2000 at 19:32 UTC
    I haven't tried this myself, but what you need to do to get this to go, is add another entry to your WriteMakefile() call, it should look like this:

    WriteMakefile( 'NAME' => 'myclass', 'VERSION_FROM' => 'myclass.pm', # finds $VERSION 'LIBS' => [''], # e.g., '-lm' 'DEFINE' => '', # e.g., '-DHAVE_SOMETHING' 'INC' => '', # e.g., '-I/usr/include/other' 'XSOPT' => '-C++', 'XS' => {'myclass.xs' => 'myclass.cc'}, );


    And you might need to add another line requesting that it clean up the .cc file when a make clean is run. The man page is a bit sketchy on that point, so the extra line you might need to add will look like this:

    'clean' => {FILES => "*.cc"}
      Thanks. I tried what you suggested. One problem is that the Makefile is still setting CC = cc so it still tries to compile with the C compiler. Here's the output:
      judyf: betaman.portsoft.com.138> make mkdir ./blib mkdir ./blib/lib mkdir ./blib/arch mkdir ./blib/arch/auto mkdir ./blib/arch/auto/myclass mkdir ./blib/lib/auto mkdir ./blib/lib/auto/myclass mkdir ./blib/man3 cp myclass.pm ./blib/lib/myclass.pm AutoSplitting ./blib/lib/myclass.pm (./blib/lib/auto/myc cc -c -O -DVERSION=\"0.01\" -DXS_VERSION=\"0.01\" perl5/sun4-solaris/5.00405/CORE myclass.cc cc: No input file specified, no output generated *** Error code 1 make: Fatal error: Command failed for target `myclass.o'
      I did an 'ls' and it turns out that myclass.cc does not exist. Neither does myclass.c for that matter. Then, I took out the line:
      'XS' => {'myclass.xs' => 'myclass.cc'}, in Makefile.PL. Then did a 'make clean' and reran ' perl Makefile.PL', then 'make'. Here's the output: <CODE> judyf: betaman.portsoft.com.138> make mkdir ./blib mkdir ./blib/lib mkdir ./blib/arch mkdir ./blib/arch/auto mkdir ./blib/arch/auto/myclass mkdir ./blib/lib/auto mkdir ./blib/lib/auto/myclassmkdir ./blib/man3 cp myclass.pm ./blib/lib/myclass.pm AutoSplitting ./blib/lib/myclass.pm (./blib/lib/auto/myclass) /bin/perl -I/usr/local/lib/perl5/sun4-solaris/5.00405 -I/usr/local/lib +/perl5 /us r/local/lib/perl5/ExtUtils/xsubpp -C++ -typemap /usr/local/lib/perl5/ +ExtUtils/t ypemap -typemap typemap myclass.xs >myclass.tc && mv myclass.tc myclas +s.c Please specify prototyping behavior for myclass.xs (see perlxs manual) cc -c -O -DVERSION=\"0.01\" -DXS_VERSION=\"0.01\" -Kpic -I/usr/ +local/lib/ perl5/sun4-solaris/5.00405/CORE myclass.c "/home/judyf/perlwork/myclass/myclass.h", line 9: undefined or not a type: class ... (and so on with rest of errors)
      Not sure why it's missing these lines in Makefile when it's in C++ mode. Also, I edited Makefile and these lines are still set to: <CODE> CC = cc LD = cc <CODE> I'll keep looking into it but if you have any further suggestions, I'm all ears. Thanks.

        I'm pretty sure that the XSOPT=>'-C++' option is only partially implemented. It only does (at most) one of something like 3 things that it should do.

        Now, I think the direction C and C++ compilers have moved is that you use "cc" to compile both C and C++ files and the compiler determines what type of code it is compiling by whether the file name ends in .c or one of .cc, .cpp, .c++, .cxx, etc., where each compiler recognizes about two different extensions for C++ code. So the CC=cc is probably not a problem. The problem is that it is generating a file named myclass.c instead of myclass.cxx.

        I managed to use C++ in XS as part of some other strange work I was doing (see the latest versions of Win32API::File, for example). I used .cxx and wrote my own rules out with sub MY::postamble. At least the latest MakeMaker knows how to compile a .cxx file if you ask it to.