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