1*c4aff060SBarry Smith #define PETSC_DLL 2*c4aff060SBarry Smith 3*c4aff060SBarry Smith #include "petsc.h" /*I "petsc.h" I*/ 4*c4aff060SBarry Smith #include "petscsys.h" /*I "petscsys.h" I*/ 5*c4aff060SBarry Smith 6*c4aff060SBarry Smith /* ---------------------------------------------------------------- */ 7*c4aff060SBarry Smith 8*c4aff060SBarry Smith #if !defined(PETSC_PYTHON_EXE) 9*c4aff060SBarry Smith #define PETSC_PYTHON_EXE "python" 10*c4aff060SBarry Smith #endif 11*c4aff060SBarry Smith 12*c4aff060SBarry Smith #undef __FUNCT__ 13*c4aff060SBarry Smith #define __FUNCT__ "PetscPythonFindExecutable" 14*c4aff060SBarry Smith static PetscErrorCode PetscPythonFindExecutable(char pythonexe[PETSC_MAX_PATH_LEN]) 15*c4aff060SBarry Smith { 16*c4aff060SBarry Smith PetscTruth flag; 17*c4aff060SBarry Smith PetscErrorCode ierr; 18*c4aff060SBarry Smith PetscFunctionBegin; 19*c4aff060SBarry Smith /* get the path for the Python interpreter executable */ 20*c4aff060SBarry Smith ierr = PetscStrncpy(pythonexe,PETSC_PYTHON_EXE,PETSC_MAX_PATH_LEN);CHKERRQ(ierr); 21*c4aff060SBarry Smith ierr = PetscOptionsGetString(PETSC_NULL,"-python",pythonexe,PETSC_MAX_PATH_LEN,&flag);CHKERRQ(ierr); 22*c4aff060SBarry Smith if (!flag || pythonexe[0]==0) { 23*c4aff060SBarry Smith ierr = PetscStrncpy(pythonexe,PETSC_PYTHON_EXE,PETSC_MAX_PATH_LEN);CHKERRQ(ierr); 24*c4aff060SBarry Smith } 25*c4aff060SBarry Smith PetscFunctionReturn(0); 26*c4aff060SBarry Smith } 27*c4aff060SBarry Smith 28*c4aff060SBarry Smith #undef __FUNCT__ 29*c4aff060SBarry Smith #define __FUNCT__ "PetscPythonFindLibrary" 30*c4aff060SBarry Smith static PetscErrorCode PetscPythonFindLibrary(char pythonexe[PETSC_MAX_PATH_LEN], 31*c4aff060SBarry Smith char pythonlib[PETSC_MAX_PATH_LEN]) 32*c4aff060SBarry Smith { 33*c4aff060SBarry Smith const char cmdline[] = "-c 'import sys; print(sys.exec_prefix); print(sys.version[:3])'"; 34*c4aff060SBarry Smith char command[PETSC_MAX_PATH_LEN+1+sizeof(cmdline)+1]; 35*c4aff060SBarry Smith char prefix[PETSC_MAX_PATH_LEN],version[8],sep[2]={PETSC_DIR_SEPARATOR, 0},*eol; 36*c4aff060SBarry Smith FILE* fp = NULL; 37*c4aff060SBarry Smith char path[PETSC_MAX_PATH_LEN+1]; 38*c4aff060SBarry Smith PetscTruth found = PETSC_FALSE; 39*c4aff060SBarry Smith PetscErrorCode ierr; 40*c4aff060SBarry Smith PetscFunctionBegin; 41*c4aff060SBarry Smith 42*c4aff060SBarry Smith #if defined(PETSC_PYTHON_LIB) 43*c4aff060SBarry Smith ierr = PetscStrcpy(pythonlib,PETSC_PYTHON_LIB);CHKERRQ(ierr); 44*c4aff060SBarry Smith PetscFunctionReturn(0); 45*c4aff060SBarry Smith #endif 46*c4aff060SBarry Smith 47*c4aff060SBarry Smith /* call Python to find out the name of the Python dynamic library */ 48*c4aff060SBarry Smith ierr = PetscStrncpy(command,pythonexe,PETSC_MAX_PATH_LEN);CHKERRQ(ierr); 49*c4aff060SBarry Smith ierr = PetscStrcat(command," ");CHKERRQ(ierr); 50*c4aff060SBarry Smith ierr = PetscStrcat(command,cmdline);CHKERRQ(ierr); 51*c4aff060SBarry Smith #if defined(PETSC_HAVE_POPEN) 52*c4aff060SBarry Smith ierr = PetscPOpen(PETSC_COMM_SELF,PETSC_NULL,command,"r",&fp);CHKERRQ(ierr); 53*c4aff060SBarry Smith if (!fgets(prefix,sizeof(prefix),fp)) 54*c4aff060SBarry Smith { SETERRQ1(PETSC_ERR_PLIB,"Python: bad output from executable: %s",pythonexe); } 55*c4aff060SBarry Smith if (!fgets(version,sizeof(version),fp)) 56*c4aff060SBarry Smith { SETERRQ1(PETSC_ERR_PLIB,"Python: bad output from executable: %s",pythonexe); } 57*c4aff060SBarry Smith ierr = PetscPClose(PETSC_COMM_SELF,fp);CHKERRQ(ierr); 58*c4aff060SBarry Smith #else 59*c4aff060SBarry Smith SETERRQ(1,"Python: Aborted due to missing popen()"); 60*c4aff060SBarry Smith #endif 61*c4aff060SBarry Smith /* remove newlines */ 62*c4aff060SBarry Smith ierr = PetscStrchr(prefix,'\n',&eol);CHKERRQ(ierr); 63*c4aff060SBarry Smith if (eol) eol[0] = 0; 64*c4aff060SBarry Smith ierr = PetscStrchr(version,'\n',&eol);CHKERRQ(ierr); 65*c4aff060SBarry Smith if (eol) eol[0] = 0; 66*c4aff060SBarry Smith 67*c4aff060SBarry Smith /* test for $prefix/lib64/libpythonX.X[.so]*/ 68*c4aff060SBarry Smith ierr = PetscStrcpy(pythonlib,prefix);CHKERRQ(ierr); 69*c4aff060SBarry Smith ierr = PetscStrcat(pythonlib,sep);CHKERRQ(ierr); 70*c4aff060SBarry Smith ierr = PetscStrcat(pythonlib,"lib64");CHKERRQ(ierr); 71*c4aff060SBarry Smith ierr = PetscTestDirectory(pythonlib,'r',&found);CHKERRQ(ierr); 72*c4aff060SBarry Smith if (found) { 73*c4aff060SBarry Smith ierr = PetscStrcat(pythonlib,sep);CHKERRQ(ierr); 74*c4aff060SBarry Smith ierr = PetscStrcat(pythonlib,"libpython");CHKERRQ(ierr); 75*c4aff060SBarry Smith ierr = PetscStrcat(pythonlib,version);CHKERRQ(ierr); 76*c4aff060SBarry Smith ierr = PetscDLLibraryRetrieve(PETSC_COMM_SELF,pythonlib,path,PETSC_MAX_PATH_LEN,&found);CHKERRQ(ierr); 77*c4aff060SBarry Smith if (found) PetscFunctionReturn(0); 78*c4aff060SBarry Smith } 79*c4aff060SBarry Smith 80*c4aff060SBarry Smith /* test for $prefix/lib/libpythonX.X[.so]*/ 81*c4aff060SBarry Smith ierr = PetscStrcpy(pythonlib,prefix);CHKERRQ(ierr); 82*c4aff060SBarry Smith ierr = PetscStrcat(pythonlib,sep);CHKERRQ(ierr); 83*c4aff060SBarry Smith ierr = PetscStrcat(pythonlib,"lib");CHKERRQ(ierr); 84*c4aff060SBarry Smith ierr = PetscTestDirectory(pythonlib,'r',&found);CHKERRQ(ierr); 85*c4aff060SBarry Smith if (found) { 86*c4aff060SBarry Smith ierr = PetscStrcat(pythonlib,sep);CHKERRQ(ierr); 87*c4aff060SBarry Smith ierr = PetscStrcat(pythonlib,"libpython");CHKERRQ(ierr); 88*c4aff060SBarry Smith ierr = PetscStrcat(pythonlib,version);CHKERRQ(ierr); 89*c4aff060SBarry Smith ierr = PetscDLLibraryRetrieve(PETSC_COMM_SELF,pythonlib,path,PETSC_MAX_PATH_LEN,&found);CHKERRQ(ierr); 90*c4aff060SBarry Smith if (found) PetscFunctionReturn(0); 91*c4aff060SBarry Smith } 92*c4aff060SBarry Smith 93*c4aff060SBarry Smith /* nothing good found */ 94*c4aff060SBarry Smith ierr = PetscMemzero(pythonlib,PETSC_MAX_PATH_LEN);CHKERRQ(ierr); 95*c4aff060SBarry Smith ierr = PetscInfo(0,"Python dynamic library not found\n");CHKERRQ(ierr); 96*c4aff060SBarry Smith 97*c4aff060SBarry Smith PetscFunctionReturn(0); 98*c4aff060SBarry Smith } 99*c4aff060SBarry Smith 100*c4aff060SBarry Smith /* ---------------------------------------------------------------- */ 101*c4aff060SBarry Smith 102*c4aff060SBarry Smith typedef struct _Py_object_t PyObject; /* fake definition */ 103*c4aff060SBarry Smith 104*c4aff060SBarry Smith static int (*Py_IsInitialized)(void); 105*c4aff060SBarry Smith static void (*Py_InitializeEx)(int); 106*c4aff060SBarry Smith static void (*Py_Finalize)(void); 107*c4aff060SBarry Smith 108*c4aff060SBarry Smith static void (*PySys_SetArgv)(int, char **); 109*c4aff060SBarry Smith static PyObject* (*PyImport_ImportModule)(const char *); 110*c4aff060SBarry Smith 111*c4aff060SBarry Smith static void (*Py_IncRef)(PyObject *); 112*c4aff060SBarry Smith static void (*Py_DecRef)(PyObject *); 113*c4aff060SBarry Smith 114*c4aff060SBarry Smith static void (*PyErr_Clear)(void); 115*c4aff060SBarry Smith static PyObject* (*PyErr_Occurred)(void); 116*c4aff060SBarry Smith 117*c4aff060SBarry Smith 118*c4aff060SBarry Smith #define PetscDLPyLibOpen(libname) \ 119*c4aff060SBarry Smith PetscDLLibraryAppend(PETSC_COMM_SELF,&DLLibrariesLoaded,libname) 120*c4aff060SBarry Smith #define PetscDLPyLibSym(symbol, value) \ 121*c4aff060SBarry Smith PetscDLLibrarySym(PETSC_COMM_SELF,&DLLibrariesLoaded,PETSC_NULL,symbol,(void**)value) 122*c4aff060SBarry Smith #define PetscDLPyLibClose(comm) \ 123*c4aff060SBarry Smith do { } while(0) 124*c4aff060SBarry Smith 125*c4aff060SBarry Smith #undef __FUNCT__ 126*c4aff060SBarry Smith #define __FUNCT__ "PetscPythonLoadLibrary" 127*c4aff060SBarry Smith static PetscErrorCode PetscPythonLoadLibrary(const char pythonlib[]) 128*c4aff060SBarry Smith { 129*c4aff060SBarry Smith PetscErrorCode ierr; 130*c4aff060SBarry Smith PetscFunctionBegin; 131*c4aff060SBarry Smith 132*c4aff060SBarry Smith /* open the Python dynamic library */ 133*c4aff060SBarry Smith ierr = PetscDLPyLibOpen(pythonlib);CHKERRQ(ierr); 134*c4aff060SBarry Smith ierr = PetscInfo1(0,"Python: loaded dynamic library %s\n", pythonlib); CHKERRQ(ierr); 135*c4aff060SBarry Smith /* look required symbols from the Python C-API */ 136*c4aff060SBarry Smith ierr = PetscDLPyLibSym("Py_IsInitialized" , &Py_IsInitialized );CHKERRQ(ierr); 137*c4aff060SBarry Smith ierr = PetscDLPyLibSym("Py_InitializeEx" , &Py_InitializeEx );CHKERRQ(ierr); 138*c4aff060SBarry Smith ierr = PetscDLPyLibSym("Py_Finalize" , &Py_Finalize );CHKERRQ(ierr); 139*c4aff060SBarry Smith ierr = PetscDLPyLibSym("PySys_SetArgv" , &PySys_SetArgv );CHKERRQ(ierr); 140*c4aff060SBarry Smith ierr = PetscDLPyLibSym("PyImport_ImportModule" , &PyImport_ImportModule );CHKERRQ(ierr); 141*c4aff060SBarry Smith ierr = PetscDLPyLibSym("Py_IncRef" , &Py_IncRef );CHKERRQ(ierr); 142*c4aff060SBarry Smith ierr = PetscDLPyLibSym("Py_DecRef" , &Py_DecRef );CHKERRQ(ierr); 143*c4aff060SBarry Smith ierr = PetscDLPyLibSym("PyErr_Clear" , &PyErr_Clear );CHKERRQ(ierr); 144*c4aff060SBarry Smith ierr = PetscDLPyLibSym("PyErr_Occurred" , &PyErr_Occurred );CHKERRQ(ierr); 145*c4aff060SBarry Smith /* XXX TODO: check that ALL symbols were there !!! */ 146*c4aff060SBarry Smith if (!Py_IsInitialized) {SETERRQ(1,"Python: failed to load symbols from dynamic library");} 147*c4aff060SBarry Smith if (!Py_InitializeEx) {SETERRQ(1,"Python: failed to load symbols from dynamic library");} 148*c4aff060SBarry Smith if (!Py_Finalize) {SETERRQ(1,"Python: failed to load symbols from dynamic library");} 149*c4aff060SBarry Smith ierr = PetscInfo(0,"Python: all required symbols loaded from Python dynamic library\n"); CHKERRQ(ierr); 150*c4aff060SBarry Smith 151*c4aff060SBarry Smith PetscFunctionReturn(0); 152*c4aff060SBarry Smith } 153*c4aff060SBarry Smith 154*c4aff060SBarry Smith /* ---------------------------------------------------------------- */ 155*c4aff060SBarry Smith 156*c4aff060SBarry Smith static char PetscPythonExe[PETSC_MAX_PATH_LEN] = { 0 }; 157*c4aff060SBarry Smith static char PetscPythonLib[PETSC_MAX_PATH_LEN] = { 0 }; 158*c4aff060SBarry Smith static PetscTruth PetscBeganPython = PETSC_FALSE; 159*c4aff060SBarry Smith 160*c4aff060SBarry Smith #undef __FUNCT__ 161*c4aff060SBarry Smith #define __FUNCT__ "PetscPythonFinalize" 162*c4aff060SBarry Smith /*@C 163*c4aff060SBarry Smith PetscPythonFinalize - Finalize Python. 164*c4aff060SBarry Smith 165*c4aff060SBarry Smith Level: intermediate 166*c4aff060SBarry Smith 167*c4aff060SBarry Smith .keywords: Python 168*c4aff060SBarry Smith @*/ 169*c4aff060SBarry Smith PetscErrorCode PETSC_DLLEXPORT PetscPythonFinalize(void) 170*c4aff060SBarry Smith { 171*c4aff060SBarry Smith PetscFunctionBegin; 172*c4aff060SBarry Smith if (PetscBeganPython) { if (Py_IsInitialized()) Py_Finalize(); } 173*c4aff060SBarry Smith PetscBeganPython = PETSC_FALSE; 174*c4aff060SBarry Smith PetscFunctionReturn(0); 175*c4aff060SBarry Smith } 176*c4aff060SBarry Smith 177*c4aff060SBarry Smith #undef __FUNCT__ 178*c4aff060SBarry Smith #define __FUNCT__ "PetscPythonInitialize" 179*c4aff060SBarry Smith /*@C 180*c4aff060SBarry Smith PetscPythonInitialize - Initialize Python and import petsc4py. 181*c4aff060SBarry Smith 182*c4aff060SBarry Smith Input Parameter: 183*c4aff060SBarry Smith + pyexe - path to the Python interpreter executable, or PETSC_NULL. 184*c4aff060SBarry Smith - pylib - full path to the Python dynamic library, or PETSC_NULL. 185*c4aff060SBarry Smith 186*c4aff060SBarry Smith Level: intermediate 187*c4aff060SBarry Smith 188*c4aff060SBarry Smith .keywords: Python 189*c4aff060SBarry Smith 190*c4aff060SBarry Smith @*/ 191*c4aff060SBarry Smith PetscErrorCode PETSC_DLLEXPORT PetscPythonInitialize(const char pyexe[],const char pylib[]) 192*c4aff060SBarry Smith { 193*c4aff060SBarry Smith int argc = 0; 194*c4aff060SBarry Smith char **argv = 0; 195*c4aff060SBarry Smith PyObject *module = 0; 196*c4aff060SBarry Smith static PetscTruth registered = PETSC_FALSE; 197*c4aff060SBarry Smith PetscErrorCode ierr; 198*c4aff060SBarry Smith PetscFunctionBegin; 199*c4aff060SBarry Smith if (PetscBeganPython) PetscFunctionReturn(0); 200*c4aff060SBarry Smith /* Python executable */ 201*c4aff060SBarry Smith if (pyexe && pyexe[0] != 0) { 202*c4aff060SBarry Smith ierr = PetscStrncpy(PetscPythonExe,pyexe,sizeof(PetscPythonExe));CHKERRQ(ierr); 203*c4aff060SBarry Smith } else { 204*c4aff060SBarry Smith ierr = PetscPythonFindExecutable(PetscPythonExe);CHKERRQ(ierr); 205*c4aff060SBarry Smith } 206*c4aff060SBarry Smith /* Python dynamic library */ 207*c4aff060SBarry Smith if (pylib && pylib[0] != 0) { 208*c4aff060SBarry Smith ierr = PetscStrncpy(PetscPythonLib,pylib,sizeof(PetscPythonLib));CHKERRQ(ierr); 209*c4aff060SBarry Smith } else { 210*c4aff060SBarry Smith ierr = PetscPythonFindLibrary(PetscPythonExe,PetscPythonLib);CHKERRQ(ierr); 211*c4aff060SBarry Smith } 212*c4aff060SBarry Smith /* dynamically load Python library */ 213*c4aff060SBarry Smith ierr = PetscPythonLoadLibrary(PetscPythonLib);CHKERRQ(ierr); 214*c4aff060SBarry Smith /* initialize Python */ 215*c4aff060SBarry Smith PetscBeganPython = PETSC_FALSE; 216*c4aff060SBarry Smith if (!Py_IsInitialized()) { 217*c4aff060SBarry Smith /* call below does not install signal handlers */ 218*c4aff060SBarry Smith Py_InitializeEx(0); 219*c4aff060SBarry Smith /* call below required to build 'sys.argv' list */ 220*c4aff060SBarry Smith ierr = PetscGetArgs(&argc,&argv);CHKERRQ(ierr); 221*c4aff060SBarry Smith if (argc && argv && argv[0]) PySys_SetArgv(argc,argv); 222*c4aff060SBarry Smith /* register finalizer */ 223*c4aff060SBarry Smith if (!registered) { 224*c4aff060SBarry Smith ierr = PetscRegisterFinalize(PetscPythonFinalize);CHKERRQ(ierr); 225*c4aff060SBarry Smith registered = PETSC_TRUE; 226*c4aff060SBarry Smith } 227*c4aff060SBarry Smith PetscBeganPython = PETSC_TRUE; 228*c4aff060SBarry Smith } 229*c4aff060SBarry Smith /* import 'petsc4py.PETSc' module */ 230*c4aff060SBarry Smith module = PyImport_ImportModule("petsc4py.PETSc"); 231*c4aff060SBarry Smith if (module) { 232*c4aff060SBarry Smith ierr = PetscInfo(0,"Python: successfully imported module 'petsc4py.PETSc'\n"); CHKERRQ(ierr); 233*c4aff060SBarry Smith Py_DecRef(module); module = 0; 234*c4aff060SBarry Smith } else { 235*c4aff060SBarry Smith SETERRQ(PETSC_ERR_PLIB,"Python: could not import module 'petsc4py.PETSc', perhaps your PYTHONPATH does not contain it\n"); 236*c4aff060SBarry Smith } 237*c4aff060SBarry Smith PetscFunctionReturn(0); 238*c4aff060SBarry Smith } 239*c4aff060SBarry Smith 240*c4aff060SBarry Smith /* ---------------------------------------------------------------- */ 241