See More

//--------------------------------------------------------------------------- #include #pragma hdrstop #include "Unit1.h" #include //--------------------------------------------------------------------------- #pragma package(smart_init) #pragma link "PythonEngine" #pragma link "PythonGUIInputOutput" #pragma resource "*.dfm" TForm1 *Form1; //--------------------------------------------------------------------------- // New Python type Point // // Constructors & Destructors // We override the constructors __fastcall TPyPoint::TPyPoint( TPythonType* APythonType ) : TPyObject(APythonType) { x = 0; y = 0; } // Don't call the Create constructor of TPyPoint, because // we call the inherited constructor CreateWith that calls // the Create constructor first, and because the constructors // are virtual, TPyPoint.Create will be automatically be called. __fastcall TPyPoint::TPyPoint( TPythonType* APythonType, PPyObject args ) : TPyObject(APythonType, args) { if (! Py::PyArg_ParseTuple( (Py::PyObject *)args, "ii:CreatePoint", &x, &y )) return; } // Type services //////////////// // Basic services PPyObject __fastcall TPyPoint::GetAttr(char * key) { TPythonEngine* eng = GetPythonEngine(); if ( strcmp(key, "x") == 0 ) return eng->VariantAsPyObject( x ); // Or return eng->PyInt_FromLong( x ); else if ( strcmp(key, "y" ) == 0 ) return eng->VariantAsPyObject( y ); // or return PyInt_FromLong( y ); else return inherited::GetAttr(key); } int __fastcall TPyPoint::SetAttr(char * key, PPyObject value) { Py::PyObject * val = (Py::PyObject *)value; if ( strcmp(key, "x") == 0 ) { if ( Py::PyArg_Parse( val, "i:Point.SetAttr", &x ) ) return 0; else return -1; } else if ( strcmp(key, "y") == 0 ) { if ( Py::PyArg_Parse( val, "i:Point.SetAttr", &y ) ) return 0; else return -1; } else return inherited::SetAttr(key, value); } PPyObject __fastcall TPyPoint::Repr(void) { TPythonEngine* eng = GetPythonEngine(); return eng->VariantAsPyObject(Format("(%d, %d)",ARRAYOFCONST((x, y)))); // or return eng->PyString_FromString( (char *)Format("(%d, %d)", ARRAYOFCONST((x, y))) ); } // Interface methods // They will be called directly by Python, so we extract the // python arguments and we call the method that will really do // the action. PPyObject __cdecl DoOffsetBy( PPyObject self, PPyObject args ) { TPyPoint * p = (TPyPoint *)PythonToDelphi(self); int dx, dy; if (! Py::PyArg_ParseTuple( (Py::PyObject *)args, "ii:OffsetBy", &dx, &dy )) return NULL; p->OffsetBy(dx, dy); TPythonEngine* eng = GetPythonEngine(); return eng->ReturnNone(); } PPyObject __cdecl DoRaiseError( PPyObject self, PPyObject args ) { TPyPoint * p = (TPyPoint *)PythonToDelphi(self); p->RaiseError(); return NULL; // we return NULL because RaiseError raised a Python error. } // Class method for registering the type interface methods void __fastcall TPyPoint::RegisterMethods(TPythonType* PythonType) { inherited::RegisterMethods(PythonType); PythonType->AddMethod( "OffsetBy", DoOffsetBy, "Point.OffsetBy( dx, dy )" ); PythonType->AddMethod( "RaiseError", DoRaiseError, "Point.RaiseError()" ); } // Methods of TPyPoint // They do the real actions on the object // It's better to split the functions that interface // Delphi to Python and the functions that do the // real implementation. void TPyPoint::OffsetBy( int dx, int dy ) { x += dx; y += dy; } // Here's an example of how you can raise errors defined // in the module linked to our type. void TPyPoint::RaiseError(void) { TPythonEngine* eng = GetPythonEngine(); // This is a simple call: // GetModule->RaiseError( "PointError", "this is an example of raising an error !" ); // This is an advanced call: // We provide the instance vars as a dictionary, so that we can intercept the // error with "except" and extract informations from the error object. // ArrayToPyDict needs a list of pairs: varName (string), varValue (anything) GetModule()->RaiseErrorObj( "EBadPoint", "this is an example of raising an error !", eng->ArrayToPyDict( ARRAYOFCONST(("a", 1, "b", 2, "c", 3)) ) ); } //--------------------------------------------------------------------------- __fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) { } //--------------------------------------------------------------------------- void __fastcall TForm1::Button1Click(TObject *Sender) { PythonEngine1->ExecStrings( Memo2->Lines ); } //--------------------------------------------------------------------------- // We need to initialize the property PyObjectClass with // the class of our Type object void __fastcall TForm1::PythonType1Initialization(TObject *Sender) { PythonType1->PyObjectClass = __classid(TPyPoint); } //---------------------------------------------------------------------------