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