Marshall.cpp
// Marshall.cpp
//
// Author David Barrett-Lennard
// (C)opyright Cedanet Pty Ltd 2007
@import "Ceda/cxPython/cxPython.h"
#include "Ceda/cxUtils/TracerUtils.h"
@def mPrint(v) = print @str(v = ) + `v`
///////////////////////////////////////////////////////////////////////////////////////////////////
/*
This example demonstrates the marshalling of a user defined class/struct by value. The
class/struct must be reflected, have a public copy constructor and assignment operator and not be
declared << -copy >>.
*/
namespace Marshall1
{
$struct+ X
{
X(int val = 15)
{
v = new int(val);
}
X(const X& rhs)
{
v = new int(*rhs.v);
}
X& operator=(const X& rhs)
{
if (this != &rhs)
{
*v = *rhs.v;
}
return *this;
}
~X()
{
delete v;
}
$ceda::int32 GetValue() const { return *v; }
ceda::int32* v;
};
$function+ X ReturnX()
{
return X(10);
}
$function+ void PassX(X val)
{
Tracer() << "PassX() received value " << val.GetValue() << '\n';
}
void Run()
{
ceda::TraceGroup g("Marshall class by value");
PyRun_SimpleString(
@strx
(
Marshall1 = rootnamespace.Marshall1
x = Marshall1.ReturnX();
Marshall1.PassX(x)
));
}
}
///////////////////////////////////////////////////////////////////////////////////////////////////
/*
Marshalling ptr<T>
*/
namespace Marshall2
{
/////////////////// Interfaces
$interface+ Ix : ceda::IObject
{
ceda::int32 GetX() const;
};
$interface+ Iy : ceda::IObject
{
ceda::int32 GetY() const;
};
$interface+ Iz : ceda::IObject
{
ceda::int32 GetZ() const;
};
$function+ void PassIx(ceda::ptr<Ix> ix)
{
Tracer() << "PassIx() received x = " << ix->GetX() << '\n';
}
$function+ void PassIy(ceda::ptr<Iy> iy)
{
Tracer() << "PassIy() received y = " << iy->GetY() << '\n';
}
$function+ void PassIz(ceda::ptr<Iz> iz)
{
Tracer() << "PassIz() received z = " << iz->GetZ() << '\n';
}
//////////////////////////////
$struct+ X isa Ix,Iy
{
X(ceda::int32 x=0,ceda::int32 y=0) : m_x(x), m_y(y) {}
ceda::int32 GetX() const { return m_x; }
ceda::int32 GetY() const { return m_y; }
ceda::int32 m_x;
ceda::int32 m_y;
};
$struct+ Y
{
$ceda::ptr<Ix> m_ix;
$ceda::ptr<Iy> m_iy;
};
$function+ Y CreateY()
{
return Y();
}
$function+ ceda::ptr<Ix> ReturnIx()
{
return new X(10,20);
}
/*
TODO:
We already have a way to convert a ClassVariableWrapper to a InterfacePtrWrapper
Need a way to convert a InterfacePtrWrapper to a ClassVariableWrapper
Proposal : Use getattr() with the name 'self'
*/
void Run()
{
ceda::TraceGroup g("Marshalling ptr<T>");
PyRun_SimpleString(
@strx
(
Marshall2 = rootnamespace.Marshall2
# ---------------------------------------------------------------------------------
# Return ptr<Ix> by value
x = Marshall2.ReturnIx();
mPrint(x)
mPrint(x.self)
# ---------------------------------------------------------------------------------
# Pass ptr<Ix> by value
Marshall2.PassIx(x)
# ---------------------------------------------------------------------------------
# Pass ptr<Ix> as ptr<Iy>
Marshall2.PassIy(x)
# ---------------------------------------------------------------------------------
# Assign to ptr<Ix> member
y = Marshall2.CreateY()
y.m_ix = x
mPrint(y.m_ix.GetX())
# ---------------------------------------------------------------------------------
# Assign to ptr<Iy> member using ptr<Ix>
y.m_iy = x
mPrint(y.m_iy.GetY())
# ---------------------------------------------------------------------------------
# Pass ptr<Ix> as ptr<Iz>
# This will fail, because x doesnt implement Iz.
try:
Marshall2.PassIz(x)
except TypeError as e:
print("Caught " + type(e).__name__ + ": " + str(e))
));
}
}
///////////////////////////////////////////////////////////////////////////////////////////////////
namespace Marshall
{
void Run()
{
Marshall1::Run();
Marshall2::Run();
}
}