Skip to content

Commit 558681c

Browse files
committed
perlxs.pod: update "Using XS With C++" section
Rewrite this section: =head2 Using XS With C++ Disclaimer: I've never written a proper C++ program. I had to (literally) dust off my 34-year old copy of Stroustrup(*) and also do some Googling. Hopefully what I've written is sane. (*) This was bought back in the days when people used to to learn things by buying books, and when I thought that I ought to know something about this new-fangled C++ thing. I never got round to reading all of it: I discovered Perl around the same time, which looked to be a lot more fun.
1 parent e8d92cd commit 558681c

File tree

2 files changed

+217
-79
lines changed

2 files changed

+217
-79
lines changed

dist/ExtUtils-ParseXS/lib/perlxs.pod

Lines changed: 216 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -4243,112 +4243,249 @@ entry will be used instead.
42434243

42444244
=head2 Using XS With C++
42454245

4246-
If an XSUB name contains C<::>, it is considered to be a C++ method.
4247-
The generated Perl function will assume that
4248-
its first argument is an object pointer. The object pointer
4249-
will be stored in a variable called THIS. The object should
4250-
have been created by C++ with the new() function and should
4251-
be blessed by Perl with the sv_setref_pv() macro. The
4252-
blessing of the object by Perl can be handled by a typemap. An example
4253-
typemap is shown at the end of this section.
4254-
4255-
If the return type of the XSUB includes C<static>, the method is considered
4256-
to be a static method. It will call the C++
4257-
function using the class::method() syntax. If the method is not static
4258-
the function will be called using the THIS-E<gt>method() syntax.
4259-
4260-
The next examples will use the following C++ class.
4261-
4262-
class color {
4263-
public:
4264-
color();
4265-
~color();
4266-
int blue();
4267-
void set_blue(int);
4246+
# Class methods
42684247

4269-
private:
4270-
int c_blue;
4271-
};
4248+
int
4249+
X::Y::new(int i)
42724250

4273-
The XSUBs for the blue() and set_blue() methods are defined with the class
4274-
name but the parameter for the object (THIS, or "self") is implicit and is
4275-
not listed.
4251+
static int
4252+
X::Y::foo(int i)
4253+
4254+
# Object methods
42764255

42774256
int
4278-
color::blue()
4257+
X::Y::bar(int i)
4258+
4259+
int
4260+
X::Y::bar2(int i) const
42794261

42804262
void
4281-
color::set_blue(val)
4282-
int val
4263+
X::Y::DESTROY()
4264+
4265+
# C-linkage function
4266+
4267+
extern "C" int
4268+
baz(int i)
4269+
42834270

4284-
Both Perl functions will expect an object as the first parameter. In the
4285-
generated C++ code the object is called C<THIS>, and the method call will
4286-
be performed on this object. So in the C++ code the blue() and set_blue()
4287-
methods will be called as this:
4271+
XS provides limited support for generating C++ (as opposed to C) output
4272+
files. Any XSUB whose name includes C<::> is treated as a C++ method. This
4273+
triggers two main changes in the way the XSUB's code is generated:
42884274

4289-
RETVAL = THIS->blue();
4275+
=over
4276+
4277+
=item *
42904278

4291-
THIS->set_blue(val);
4279+
An implicit first argument is added. For class methods, this will be
4280+
called C<CLASS> and will be of type C<char *>. For object methods, it will
4281+
be called C<THIS> and be of type C<X::Y *> (where C<X::Y::> is the prefix
4282+
of the XSUB's name). XSUBs are treated as class methods if their name is
4283+
C<new> or their return type has the C<static> prefix.
4284+
4285+
=item *
4286+
4287+
Any autocall will generate an appropriate C++ method call rather then a C
4288+
function call. In particular, based on the examples above:
4289+
4290+
new: RETVAL = new X::Y(i);
4291+
static foo: RETVAL = X::Y::foo(i);
4292+
bar (and bar2): RETVAL = THIS->bar(i);
4293+
DESTROY: delete THIS;
4294+
4295+
=item *
42924296

4293-
You could also write a single get/set method using an optional argument:
4297+
In addition, if the XSUB declaration has a trailing C<const>, then the
4298+
type of C<THIS> will be declared as C<const X::Y *>.
4299+
4300+
=back
4301+
4302+
This is mostly syntactic sugar. The C<bar> XSUB declaration above could be
4303+
written longhand as:
42944304

42954305
int
4296-
color::blue(val = NO_INIT)
4297-
int val
4298-
PROTOTYPE $;$
4299-
CODE:
4300-
if (items > 1)
4301-
THIS->set_blue(val);
4302-
RETVAL = THIS->blue();
4303-
OUTPUT:
4304-
RETVAL
4306+
bar(X::Y* THIS, int i)
4307+
CODE:
4308+
RETVAL = THIS->foo(i);
4309+
OUTPUT:
4310+
RETVAL
43054311

4306-
If the function's name is B<DESTROY> then the C++ C<delete> function will be
4307-
called and C<THIS> will be given as its parameter. The generated C++ code for
4312+
Note that the type of C<THIS> (and, since Perl 5.42, C<CLASS>) can be
4313+
overridden with a line in an C<INPUT> section:
43084314

4309-
void
4310-
color::DESTROY()
4315+
int
4316+
X::Y::bar(int i)
4317+
X::Y::Z *THIS
43114318

4312-
will look like this:
4319+
Finally, a plain C XSUB declaration can be prefixed with C<extern "C"> to
4320+
give that XSUB C linkage.
43134321

4314-
color *THIS = ...; // Initialized as in typemap
4322+
Some of the methods above might be called from Perl using code like this:
43154323

4316-
delete THIS;
4324+
{
4325+
my $obj = Foo::Bar->new(1);
4326+
$obj->bar(2);
4327+
# implicit $obj->DESTROY();
4328+
}
43174329

4318-
If the function's name is B<new> then the C++ C<new> function will be called
4319-
to create a dynamic C++ object. The XSUB will expect the class name, which
4320-
will be kept in a variable called C<CLASS>, to be given as the first
4321-
argument.
4330+
This example uses C<Foo::Bar> rather than C<X::Y> to emphasise that the
4331+
name of the C++ class needn't follow the Perl package name.
43224332

4323-
color *
4324-
color::new()
4333+
The call to C<new()> will pass the string C<"Foo::Bar"> as the first
4334+
argument, which can be used to allow multiple Perl classes to share the
4335+
same C<new()> method. In the simple worked example below, the package name
4336+
is hard-coded and that parameter is unused. The C<new()> method is
4337+
expected to return a Perl object which in some way has a pointer to the
4338+
underlying C++ object embedded within it. This is similar to the
4339+
L</T_PTROBJ and opaque handles> example of wrapping a C library which
4340+
uses a handle, although with a subtle difference, as explained below.
43254341

4326-
The generated C++ code will call C<new>.
4342+
Calling C<bar()> passes this Perl object as the first argument, which the
4343+
typemap will use to extract the C++ object pointer and assign to the
4344+
C<THIS> auto variable.
43274345

4328-
RETVAL = new color();
4346+
=head3 A complete C++ example
43294347

4330-
The following is an example of a typemap that could be used for this C++
4331-
example.
4348+
First, you need to tell MakeMaker or similar that the generated file
4349+
should be compiled using a C++ compiler. For basic experimentation you may
4350+
be able to get by with just adding these two lines to the
4351+
C<WriteMakefile()> method call in F<Makefile.PL>:
43324352

4333-
TYPEMAP
4334-
color * O_OBJECT
4353+
CC => 'c++',
4354+
LD => '$(CC)',
43354355

4336-
OUTPUT
4337-
# The Perl object is blessed into 'CLASS', which should be a
4338-
# char* having the name of the package for the blessing.
4339-
O_OBJECT
4340-
sv_setref_pv($arg, CLASS, (void*)$var);
4356+
but for portability in production use, you may want to use something like
4357+
L<ExtUtils::CppGuess> to automatically generate the correct options for
4358+
L<ExtUtils::MakeMaker> or L<Module::Build> based on which C++ compiler
4359+
is available.
4360+
4361+
Then create a C<.xs> file like this:
4362+
4363+
#define PERL_NO_GET_CONTEXT
4364+
4365+
#include "EXTERN.h"
4366+
#include "perl.h"
4367+
#include "XSUB.h"
4368+
#include "ppport.h"
4369+
4370+
namespace Paint {
4371+
class color {
4372+
int c_R;
4373+
int c_G;
4374+
int c_B;
4375+
public:
4376+
color(int r, int g, int b) { c_R = r; c_G = g; c_B = b; }
4377+
~color() { printf("destructor called\n"); }
4378+
int blue() { return c_B; }
4379+
void set_blue(int b) { c_B = b; };
4380+
// and similar for red, green
4381+
};
4382+
}
4383+
4384+
typedef Paint::color Paint__color;
4385+
4386+
MODULE = Foo::Bar PACKAGE = Foo::Bar
4387+
4388+
PROTOTYPES: DISABLE
4389+
4390+
TYPEMAP: <<EOF
4391+
Paint::color * T_PKG_OBJ
43414392

43424393
INPUT
4343-
O_OBJECT
4344-
if (sv_isobject($arg) && (SvTYPE(SvRV($arg)) == SVt_PVMG))
4345-
$var = ($type)SvIV((SV*)SvRV($arg));
4346-
else {
4347-
warn(\"${Package}::$func_name() -- \"
4348-
\"$var is not a blessed SV reference\");
4349-
XSRETURN_UNDEF;
4350-
}
4394+
T_PKG_OBJ
4395+
SvGETMAGIC($arg);
4396+
if (SvROK($arg) && sv_derived_from($arg, "$Package")) {
4397+
IV tmp = SvIV((SV*)SvRV($arg));
4398+
$var = INT2PTR($type,tmp);
4399+
}
4400+
else {
4401+
const char* refstr = SvROK($arg)
4402+
? "" : SvOK($arg) ? "scalar " : "undef";
4403+
Perl_croak_nocontext(
4404+
"%s: Expected %s to be of type %s; got %s%"
4405+
SVf " instead",
4406+
${$ALIAS?\q[GvNAME(CvGV(cv))]:\qq["$pname"]},
4407+
"$var", "$Package",
4408+
refstr, $arg
4409+
);
4410+
}
4411+
4412+
T_PKG_REF
4413+
SvGETMAGIC($arg);
4414+
if (SvROK($arg)) {
4415+
IV tmp = SvIV((SV*)SvRV($arg));
4416+
$var = INT2PTR($type,tmp);
4417+
}
4418+
else
4419+
Perl_croak_nocontext("%s: %s is not a reference",
4420+
${$ALIAS?\q[GvNAME(CvGV(cv))]:\qq["$pname"]},
4421+
"$var")
4422+
4423+
OUTPUT
4424+
T_PKG_OBJ
4425+
sv_setref_pv($arg, "$Package", (void*)$var);
4426+
4427+
EOF
4428+
4429+
Paint::color *
4430+
Paint::color::new(int r, int g, int b)
4431+
4432+
int
4433+
Paint::color::blue()
4434+
4435+
void
4436+
Paint::color::set_blue(int b)
4437+
4438+
void
4439+
Paint::color::DESTROY()
4440+
4441+
In the C part of the XS file (or this case, the C++ part), a trivial
4442+
example C++ class is defined. This would more typically be a pre-existing
4443+
library with just the appropriate C<#include>. The example includes a
4444+
namespace to make it clearer when something is a namespace, class name or
4445+
Perl package. The Perl package is called C<Foo::Bar> rather than
4446+
C<Paint::color> to again distinguish it. You could however call the Perl
4447+
package C<Paint::color> if you desired.
4448+
4449+
A single typedef follows to allow for XS-mangled class names, as explained
4450+
in L</Fully-qualified type names and Perl objects>.
4451+
4452+
Then the C<MODULE> line starts the XS part of the file.
4453+
4454+
Then there follows a full definition of a new typemap called C<T_PKG_OBJ>.
4455+
This is actually a direct copy of the C<T_PTROBJ> typmap found in the
4456+
system typemap file, except that all occurrences of C<$ntype> have been
4457+
replaced with C<$Package>. It serves the same basic purpose as
4458+
C<T_PTROBJ>: embedding a pointer within a new blessed Perl object,
4459+
and later, retrieving that pointer from the object. The difference is in
4460+
terms of what package the object is blessed into. C<T_PTROBJ> expects the
4461+
type name (C<Paint::color>) to already be a pointer type, but with a C++
4462+
XSUB, the implicit C<THIS> argument is automatically declared to be of
4463+
type C<Paint::color *> (so C<Paint::color> itself isn't necessarily a
4464+
pointer type). In addition, when the Perl and C++ class names differ we
4465+
want the object to be blessed using the Perl package name, not the C++
4466+
class name. In this example, the actual values of the two variables when
4467+
the typemap template is being evaled, are:
4468+
4469+
$ntype = "Paint::colorPtr";
4470+
$Package = "Foo::Bar";
4471+
4472+
The tyemap also includes an INPUT definition for C<T_PKG_REF>, which is an
4473+
I<exact> copy of C<T_PTRREF>. This is needed because, as an optimisation,
4474+
the XS parser automatically renames an INPUT typemap using C<s/OBJ$/REF/>
4475+
if the name of the XSUB is C<DESTROY>, on the grounds that it's not
4476+
necessary to to check that the object is the right class.
4477+
4478+
Finally the XS file includes a few XSUBs which are wrappers around the
4479+
class' methods.
4480+
4481+
This class might be used like this:
4482+
4483+
use Foo::Bar;
43514484

4485+
my $color = Foo::Bar->new(0x10, 0x20, 0xff);
4486+
printf "blue=%d\n", $color->blue(); # prints 255
4487+
$color->set_blue(0x80);
4488+
printf "blue=%d\n", $color->blue(); # prints 128
43524489

43534490
=head2 Safely Storing Static Data in XS
43544491

t/porting/known_pod_issues.dat

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,7 @@ exit(3)
123123
Expect
124124
Exporter::Easy
125125
ExtUtils::Constant::ProxySubs
126+
ExtUtils::CppGuess
126127
fchdir(2)
127128
fchmod(2)
128129
fchown(2)

0 commit comments

Comments
 (0)