Hi James,

while I have a fair amount of experience with wrapping C++ using XS, it's one of those things I have to relearn almost every time I use it.

On 04/09/2011 08:25 AM, James Shirley wrote:
Hi, I'm trying to write a XS routine to return a point to a c++ class to
be accessible from perl..

I'm new to XS, so i've been following:

http://www.johnkeiser.com/perl-xs-c++.html

and

http://search.cpan.org/~dmr/CookBookB-19960430/

If you're interested in a different approach, have a look at ExtUtils::XSpp (and possibly Module::Build::With::WithXSpp) and the slides from my talk at YAPC::EU in Pisa, 2010: http://steffen-mueller.net/talks/xspp/

ExtUtils::XSpp generates XS for wrapping C++. That means you can even look at the generated XS to steal from it.

However when I try make the xs generated code, i get the following
compiler error:

g++ -c  -I. -D_REENTRANT -D_GNU_SOURCE -DDEBIAN -fno-strict-aliasing
-pipe -fstack-protector -I/usr/local/include -D_LARGEFILE_SOURCE
-D_FILE_OFFSET_BITS=64 -O2 -g   -DVERSION=\"0.01\" -DXS_VERSION=\"0.01\"
-fPIC "-I/usr/lib/perl/5.10/CORE"   MyPackage.c
MyPackage.c: In function ‘void XS_MyPackage_child(PerlInterpreter*, CV*)’:
MyPackage.c:168: error: ‘CLASS’ was not declared in this scope
make: *** [MyPackage.o] Error 1

I assume I'm doing something wrong in the child method, however i lifted
this code out of one of the CookBookB examples..

MyClass *
MyClass::child()
   CODE:
     RETVAL = (MyClass *)safemalloc( sizeof(MyClass) );
     *RETVAL = THIS->child();


Hmm. Generally, look at the C(++) code that is generated by xsubpp. In a lot of cases, it is more instructive for debugging than XS.

In this case, I bet that your typemap for O_OBJECT uses the CLASS (C) variable for finding the Perl class name to bless the new object into. The code for setting CLASS is generated by xsubpp/ExtUtils::ParseXS. Unfortunately, there's some special case logic for new() methods. Quoting from the newest EU::ParseXS:

      my $arg0 = ((defined($static) or $func_name eq 'new')
          ? "CLASS" : "THIS");

Yikes. A better solution for the preprocessor would be to have an XS attribute/decorator that indicates "this requires CLASS to be set" and/or "this is a constructor" or whatever. Hmm, it's actually something that should be part of the typemap. "Please set CLASS for this typemap". One can dream. But I'll certainly push this on top of the stack of things to look into wrt. rethinking how typemaps work at the upcoming QA hackathon. Any input would be welcome on this.

Getting back to your problem: You could work around this by creating a new Perl object manually in your XS wrapper (with the known class name) and pushing it on the stack manually, too. In that case, set the return type of your XSUB to void. This is what your typemap normally does for you, so you can take the code from there. It probably involves at least the XPUSHs macro and likely either sv_bless or sv_setref_iv or another sv_setref_* macro. See perlapi.pod.

Best regards,
Steffen

Reply via email to