# Perl wrapping for the &Cpp; objects

The subject of this section is not a part of the &Cpp; API as such but the connection between the &Cpp; and Perl APIs. You need to bother about it only if you want to write more of the components in &Cpp; and export them into Perl.

When exporting the &Cpp; (or any compiled language) API into Perl (or into any scripting language) there are two things to consider:

1. The script must never crash the interpterer. The interpreted program might die but the interpreter itself must never crash. If you've ever dealt with

       wksh

   (not thankfully long dead), you know how horrible is the debugging of such crashes.
2. Perl has its memory management by reference counting, which needs to be married with the memory management at the &Cpp; level.

The solution to the second problem is fairly straightforward: have an intermediate wrapper structure. Perl has its reference counting for the pointer to this structure. When you construct a Perl object, return the pointer to a newly allocated instance of this structure. When the Perl reference count goes down to zero, it calls the method

    DESTROY

for this object, and then you destroy this structure.

And inside this structure will be the &Cpp; reference to the actual &Cpp; object. When the wrapper structure gets created, it gets a new reference and when the wrapper structure gets destroyed, it releases this reference.

Here is a small example of how the RowType object gets created and destroyed in the Perl XS code, using the wrapper structure WrapRowType:

    WrapRowType *
    Triceps::RowType::new(...)
    	CODE:
    		RETVAL = NULL; // shut up the warning
    		try { do {
    			RowType::FieldVec fld;

    			clearErrMsg();
    			...
    			Onceref rt = new CompactRowType(fld);
    			Erref err = rt->getErrors();
    			if (err->hasError()) {
    				throw Exception::f(err, "Triceps::RowType::new: incorrect data");
    			}

    			RETVAL = new WrapRowType(rt);
    		} while(0); } TRICEPS_CATCH_CROAK;
    	OUTPUT:
    		RETVAL

    void
    DESTROY(WrapRowType *self)
    	CODE:
    		// warn("RowType destroyed!");
    		delete self;

This example also shows the way the Triceps XS code deals with the conversion of the &Cpp; Exceptions to the Perl confessions. The

    while(0)

part is a hold-over from the earlier implementation of error handling that allows to set the error message directly in a buffer and then do a

    break

to jump to the end of the pseudo-loop. The new way is the throwing of Exceptions. The shown code is a hybrid that handles both. The handling itself is done in the macro

    TRICEPS_CATCH_CROAK

.

Now let's look more in-depth at the first problem. How does Perl know to call a particular XS method for a object? From the package this object is blessed to. If the package happens to be an XS package, the XS method will be called. However it's entirely possible to re-bless the object to a completely different package. If the user does this, a completely wrong method may be called and will crash when it tries to reach a wrong object at the pointer.

Things get even worse for the other arguments of the methods. For example, the argument

    other

here:

    int
    equals(WrapRowType *self, WrapRowType *other)

Well, Perl lets you provide a code snippet for the

    typemap

file that would check that the object is as expected. But how would that snippet know? Going just by the blessed package is unreliable.

Triceps solves this problem by placing an 8-byte magic code at the front of every wrap object. Each class has its own magic value for this field. 8 bytes allow to have great many unique codes, and is quick to check because it's just one CPU word.

This magic code is defined in the &Cpp; part in

    wrap/Wrap.h

as:

    struct WrapMagic {
    	~WrapMagic()
    	{
    		(*(int64_t *)v_) = 0; // makes sure that it gets invalidated
    	}

    	char v_[8]; // 8 bytes to make a single 64-bit comparison

    	bool operator!=(const WrapMagic &wm) const
    	{
    		return (*(int64_t *)v_) != (*(int64_t *)wm.v_);
    	}
    };

Then the wrapper is implemented as follows:

    template
    class Wrap
    {
    public:
    	Wrap(Onceref r) :
    		magic_(magic),
    		ref_(r)
    	{ }

    	// returns true if the magic value is bad
    	bool badMagic() const
    	{
    		return magic_ != magic;
    	}

    	Class *get() const
    	{
    		return ref_.get();
    	}

    	operator Class*() const
    	{
    		return ref_.get();
    	}

    public:
    	WrapMagic magic_;
    	Autoref ref_; // referenced value
    private:
    	Wrap();
    };

The check is done with the method

    badMagic()

.

And the

    typemap

entry is:

    O_WRAP_OBJECT
    	if( sv_isobject($arg) && (SvTYPE(SvRV($arg)) == SVt_PVMG) ) {
    		$var = ($type)SvIV((SV*)SvRV( $arg ));
    		if ($var == 0 || $var->badMagic()) {
    			croakWithMsg( \"${Package}::$func_name(): $var has an incorrect magic for $ntype\" );
    		}
    	} else{
    		croakWithMsg( \"${Package}::$func_name(): $var is not a blessed SV reference to $ntype\" );
    	}

It checks that this is an object, of an XS package, and then that the pointer to the C/&Cpp; object is not NULL, and that the value at this pointer starts with the right magic.

    croakWithMsg()

is the Triceps function for building the confession trace and then croaking with it.

The template shown above is normally used through a macro that substitutes the repeated values from one source. For example, the definition for the RowType wrapper is:

    DEFINE_WRAP(RowType);

The static definition of the magic code that the macro passes to the template is defined in

    wrap/Wrap.cpp

:

    WrapMagic magicWrapRowType = { "RowType" };

Just make sure that the string contains no more than 7 characters.

Some objects in Triceps are reached through the special references that know both the object and its type (such as rows and row handles). For them there is a separate template and a separate macro:

    DEFINE_WRAP2(const RowType, Rowref, Row);
    DEFINE_WRAP2(Table, Rhref, RowHandle);

The arguments are the type class, the reference class and finally the object class itself.

And there is one more twist: sometimes the objects are self-contained but when you use them, you must use them only with a correct parent object. Right now there is only one such class: the Tray must be used with its correct Unit, and the Perl code checks it. In this case the wrapper has the reference to both Tray and the Unit, and is defined as:

    DEFINE_WRAP_IDENT(Unit, Tray);

Triceps has a substantial library of helper methods and objects for wrappig the &Cpp; objects, located in the Perl part of the code. Many of them are located in

    TricepsPerl.h

. Feel free to refer to them if you need to, but for now they are out of scope of the documentation.

Just one more thing: Perl is not happy about sharing the objects between multiple threads. Even when a &Cpp; object is OK with multithreading, Perl requires the separate wrappers to be created for it from each thread. When a new Perl thread is started, Perl can not properly ask the XS code to split the wrappers, so instead all the objects need to be invalidated in the new thread. To do that, the XS package needs to define the method

    CLONE_SKIP

:

    int
    CLONE_SKIP(...)
    	CODE:
    		RETVAL = 1;
    	OUTPUT:
    		RETVAL

wrapper
multithreading
XS