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