Re: XS C++ return class pointers

[email protected] (Steffen Mueller)
Newsgroups perl.xs
Message-ID <[email protected]>
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
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.