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