/*************************************************************************** gdlpython.cpp - python embedded in GDL ------------------- begin : July 22 2002 copyright : (C) 2002 by Marc Schellens email : m_schellens@users.sourceforge.net ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifdef INCLUDE_GDLPYTHON_CPP //#include "includefirst.hpp" // this part contains variable conversion stuff // used by both GDL embedded in python and python embedded in GDL #if defined(USE_PYTHON) || defined(PYTHON_MODULE) #include //#include //#include //#include "datatypes.hpp" //#include "envt.hpp" //#include "objects.hpp" using namespace std; #if PY_MAJOR_VERSION >= 3 #include std::nullptr_t PythonInit() { if( Py_IsInitialized()) return 0; #else void PythonInit() { if( Py_IsInitialized()) return; #endif Py_Initialize(); // signal handlers? static int argc = 1; #if PY_MAJOR_VERSION >= 3 static wchar_t* arg0 = Py_DecodeLocale("./py/python.exe",NULL); static wchar_t* argv[] = {arg0}; #else static char* arg0 = (char*)"./py/python.exe"; static char* argv[] = {arg0}; #endif PySys_SetArgv(argc, argv); // http://docs.scipy.org/doc/numpy/reference/c-api.array.html#miscellaneous import_array(); #if PY_MAJOR_VERSION >= 3 return 0; #endif } void PythonEnd() { // was not possible with numarray (numarray cannot be restarted) // but now we use Numpy??? (TODO/FIXME) //if( !Py_IsInitialized()) return; //Py_Finalize(); } template< typename T> T* NewFromPyArrayObject( const dimension& dim, PyArrayObject *array) { T* res = new T( dim, BaseGDL::NOZERO); SizeT nEl = res->N_Elements(); typename T::Ty* dPtr = reinterpret_cast( PyArray_DATA(array)); for( SizeT i=0; i= 3 if( PyUnicode_Check( pyObj)) { return new DStringGDL( PyUnicode_AsUTF8( pyObj)); } #else if( PyString_Check( pyObj)) { return new DStringGDL( PyString_AsString( pyObj)); } if( PyInt_Check( pyObj)) { return new DLongGDL( PyInt_AsLong( pyObj)); } #endif if( PyLong_Check( pyObj)) { return new DLongGDL( PyLong_AsLong( pyObj)); } if( PyFloat_Check( pyObj)) { return new DDoubleGDL( PyFloat_AsDouble( pyObj)); } if( PyComplex_Check( pyObj)) { DDouble re,im; re = PyComplex_RealAsDouble( pyObj); im = PyComplex_ImagAsDouble( pyObj); return new DComplexDblGDL( DComplexDbl( re, im)); } throw GDLException( "Cannot convert python scalar.") ; } // make array contiguous PyArrayObject* array = PyArray_GETCONTIGUOUS( reinterpret_cast< PyArrayObject *>( pyObj)); if( array == NULL) throw GDLException( "Error getting python array.") ; int nDim = PyArray_NDIM(array); SizeT dimArr[ MAXRANK]; if( nDim > MAXRANK) { Warning( "Python array has more than "+MAXRANK_STR+ " dimensions. Extending last one."); SizeT lastDim = PyArray_DIM(array, MAXRANK-1); for( SizeT i=MAXRANK; itype_num) { case NPY_UINT8: //GDL_BYTE return NewFromPyArrayObject< DByteGDL>( dim, array); case NPY_INT16: //GDL_INT return NewFromPyArrayObject< DIntGDL>( dim, array); case NPY_INT32: //GDL_LONG return NewFromPyArrayObject< DLongGDL>( dim, array); case NPY_FLOAT32: //GDL_FLOAT return NewFromPyArrayObject< DFloatGDL>( dim, array); case NPY_FLOAT64: //GDL_DOUBLE return NewFromPyArrayObject< DDoubleGDL>( dim, array); case NPY_COMPLEX64: //GDL_COMPLEX return NewFromPyArrayObject< DComplexGDL>( dim, array); case NPY_COMPLEX128: //GDL_COMPLEXDBL return NewFromPyArrayObject< DComplexDblGDL>( dim, array); case NPY_UINT16: //GDL_UINT* return NewFromPyArrayObject< DUIntGDL>( dim, array); case NPY_UINT32: //GDL_ULONG* return NewFromPyArrayObject< DULongGDL>( dim, array); default: Py_DECREF(array); // must be decremented throw GDLException( "FromPython: Unknown array type.") ; } return NULL; // compiler shut-up } // you can compile GDL as a python module without supporting // python *within* GDL #ifdef USE_PYTHON namespace lib { using namespace std; BaseGDL* gdlpython( EnvT* e, int kIx) { PythonInit(); SizeT nParam = e->NParam(); static int argvIx = e->KeywordIx( "ARGV"); BaseGDL* argv1 = e->GetKW( argvIx); if( argv1 != NULL) { DStringGDL* argvS = dynamic_cast( argv1); if( argvS == NULL) e->Throw( "ARGV keyword must be of type STRING."); int argc = argvS->N_Elements(); #if PY_MAJOR_VERSION >= 3 wchar_t** argv = new wchar_t*[ argc]; #else char** argv = new char*[ argc]; #endif // python copies the value -> treats it as const for( int i=0; i= 3 argv[i] = Py_DecodeLocale(const_cast((*argvS)[ i].c_str()), NULL); #else argv[i] = const_cast((*argvS)[ i].c_str()); #endif PySys_SetArgv(argc, argv); delete[] argv; } if( nParam < 2 && kIx != -1) e->Throw( "Function must have at least 2 parameters."); if( nParam == 0) return NULL; // ok, just keywords DString module; e->AssureScalarPar( 0, module); // PyObject* pName = PyString_FromString( module.c_str()); // // Error checking of pName left out // PyObject* pModule = PyImport_Import(pName); // Py_DECREF(pName); PyObject* pModule = PyImport_ImportModule(const_cast(module.c_str())); if (pModule == NULL) { PyErr_Print(); e->Throw( "Failed to load module: "+module); } if( nParam == 1) { Py_DECREF(pModule); return NULL; // ok, only load module } DString function; e->AssureScalarPar( 1, function); PyObject* pDict = PyModule_GetDict(pModule); /* pDict is a borrowed reference */ PyObject* pFunc = PyDict_GetItemString(pDict, function.c_str()); /* pFunc: Borrowed reference */ if( !(pFunc && PyCallable_Check(pFunc))) { if (PyErr_Occurred()) PyErr_Print(); e->Throw( "Cannot find function: "+function); } PyObject* pArgs = PyTuple_New( nParam-2); for( SizeT i = 2; iGetParDefined( i); PyObject* pValue = actPar->ToPython(); if (!pValue) { Py_DECREF(pArgs); Py_DECREF(pModule); e->Throw( "Cannot convert value: "+ e->GetParString( i)); } /* pValue reference stolen here: */ PyTuple_SetItem(pArgs, i-2, pValue); } PyObject* pResult = PyObject_CallObject(pFunc, pArgs); Py_DECREF(pArgs); Py_DECREF(pModule); // pDict and pFunc are borrowed and must not be Py_DECREF-ed if( pResult == NULL) { PyErr_Print(); e->Throw( "Call failed: "+module+"."+function); } if( kIx == -1) // called as procedures { Py_DECREF(pResult); return NULL; } // as function BaseGDL* res; if( pResult == Py_None) { Py_DECREF(pResult); BaseGDL* defRet = e->GetKW( kIx); if( defRet == NULL) e->Throw( "Function returned 'None' " "and DEFAULTRETURN not defined."); res = defRet->Dup(); } else { try { res = FromPython( pResult); Py_DECREF(pResult); } catch(...) { Py_DECREF(pResult); throw; } } return res; } // GDL PYTHON procedure // PYTHON,module,function[,args] void gdlpython_pro( EnvT* e) { gdlpython( e, -1); } // GDL PYTHON function BaseGDL* gdlpython_fun( EnvT* e) { static int kIx = e->KeywordIx( "DEFAULTRETURNVALUE"); return gdlpython( e, kIx); } } // namespace #endif // #ifdef USE_PYTHON #endif // #if defined(USE_PYTHON) || defined(PYTHON_MODULE) #endif // #ifdef INCLUDE_GDLPYTHON_CPP