Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages  

py_vmd.C

Go to the documentation of this file.
00001 
00002 #include "py_commands.h"
00003 #include "vmd.h"
00004 #include "DisplayDevice.h"
00005 #include "UIText.h"
00006 
00007 #ifdef VMDTCL
00008 #include <tcl.h>
00009 #endif
00010 
00011 static PyObject *py_vmdupdate(PyObject *self, PyObject *args) {
00012   VMDApp *app;
00013   if (!(app = get_vmdapp())) {
00014     fprintf(stderr, "no app!!\n");
00015     Py_INCREF(Py_None);
00016     return Py_None;
00017   }
00018   return as_pyint(app->VMDupdate(1));
00019 }
00020 
00021 static const char exit_doc[] =
00022 "Exits VMD\n\n"
00023 "Args:\n"
00024 "    message (str): Message to print\n"
00025 "    code (int): Code to return. Defaults to 0 (normal exit)\n"
00026 "    delay (int): Number of seconds to delay before exiting. Defaults to 0\n";
00027 static PyObject *py_vmdexit(PyObject *self, PyObject *args, PyObject *kwargs)
00028 {
00029   const char *kwnames[] = {"message", "code", "delay", NULL};
00030   int code = 0, pauseseconds = 0;
00031   VMDApp *app;
00032   char *msg;
00033 
00034   if (!PyArg_ParseTupleAndKeywords(args, kwargs,"s|ii:vmd.VMDupdate",
00035                                    (char**) kwnames, &msg, &code,
00036                                    &pauseseconds))
00037     return NULL;
00038 
00039   if (!(app = get_vmdapp()))
00040     return NULL;
00041 
00042   app->VMDexit(msg, code, pauseseconds);
00043   // don't call VMDshutdown, because calling Tcl_Finalize() crashes Tkinter
00044   // Maybe add a callback to the Python atexit module?
00045   Py_INCREF(Py_None);
00046   return Py_None;
00047 }
00048 
00049 #ifdef VMDTCL
00050 static const char evaltcl_doc[] =
00051 "Evaluates a command in the TCL interpreter. This can be useful for accessing "
00052 "functionality that is not yet implemented via the Python interface.\n\n"
00053 "Args:\n"
00054 "    command (str): TCL command to evaluate\n"
00055 "Returns:\n"
00056 "    (str) Output from the TCL interpreter";
00057 static PyObject *py_evaltcl(PyObject *self, PyObject *args, PyObject *kwargs)
00058 {
00059   const char *kwnames[] = {"command", NULL};
00060   const char *cmd, *result;
00061   Tcl_Interp *interp;
00062   VMDApp *app;
00063 
00064   if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s:vmd.evaltcl",
00065                                    (char**) kwnames, &cmd))
00066     return NULL;
00067 
00068   if (!(app = get_vmdapp()))
00069     return NULL;
00070 
00071   interp = app->uiText->get_tcl_interp();
00072   int rc = Tcl_Eval(interp, cmd);
00073   result = Tcl_GetStringResult(interp);
00074 
00075   if (rc != TCL_OK) {
00076     PyErr_SetString(PyExc_ValueError, result);
00077     return NULL;
00078   }
00079   return as_pystring(result);
00080 }
00081 #endif
00082 
00083 static PyMethodDef VMDAppMethods [] = {
00084     {"VMDupdate", (PyCFunction) py_vmdupdate, METH_VARARGS },
00085     {"VMDexit", (PyCFunction) py_vmdexit, METH_VARARGS | METH_KEYWORDS, exit_doc },
00086 #ifdef VMDTCL
00087     {"VMDevaltcl", (PyCFunction) py_evaltcl, METH_VARARGS | METH_KEYWORDS, evaltcl_doc },
00088     {"evaltcl", (PyCFunction) py_evaltcl, METH_VARARGS | METH_KEYWORDS, evaltcl_doc},
00089 #endif
00090     { NULL, NULL }
00091 };
00092 
00093 static VMDApp *the_app = NULL;
00094 static PyThreadState *event_tstate = NULL;
00095 
00096 #if defined(VMD_SHARED)
00097 static int vmd_input_hook() {
00098   if (the_app) {
00099     the_app->VMDupdate(1);
00100   }
00101   PyEval_RestoreThread(event_tstate);
00102   PyRun_SimpleString(
00103       "try:\n"
00104       "\timport Tkinter\n"
00105       "\twhile Tkinter.tkinter.dooneevent(Tkinter.tkinter.DONT_WAIT):\n"
00106       "\t\tpass\n"
00107       "except:\n"
00108       "\tpass\n");
00109   PyEval_SaveThread();
00110   return 0;
00111 }
00112 #endif
00113 
00114 static const char vmd_moddoc[] =
00115 "The main VMD python module. Provides access to the `evaltcl` method for "
00116 "accessing features not yet available in the Python interface. When VMD "
00117 "is built as a standalone Python module, the vmd module serves as an access "
00118 "point for all other modules, such as `vmd.molecule` for example";
00119 
00120 #if PY_MAJOR_VERSION >= 3
00121 static struct PyModuleDef vmddef = {
00122   PyModuleDef_HEAD_INIT,
00123   "vmd",
00124   vmd_moddoc,
00125   -1,
00126   VMDAppMethods,
00127 };
00128 
00129 #define INITERROR return NULL
00130 extern "C" PyObject* PyInit_vmd() {
00131 #else
00132 #define INITERROR return
00133 extern "C" void initvmd() {
00134 #endif
00135   // Assume that VMD should not initialize or use MPI
00136   // It is conceivable we would want to be able to load the VMD
00137   // Python module into a MPI-based Python run, and enable the
00138   // MPI features of VMD, but we'll have to determine the best way
00139   // to detect this and it will need to be tested since we may have
00140   // to handle this case differently than the normal MPI case where
00141   // VMD explicitly does MPI initialization and shutdown itself.
00142   int mpienabled = 0;
00143 
00144   // If there's already a VMDapp in get_vmdapp, then we must be running
00145   // inside a standalone VMD instead of being loaded as a python extension.
00146   // Don't throw an error - just load the methods for interoperability
00147   // in case vmd.so is in the PYTHONPATH of the standalone application.
00148   if (get_vmdapp()) {
00149 #if PY_MAJOR_VERSION >= 3
00150   return PyModule_Create(&vmddef);
00151 #else
00152   (void)Py_InitModule3("vmd", VMDAppMethods, vmd_moddoc);
00153   return;
00154 #endif
00155   }
00156 
00157   int argc = 1;
00158   char *argv[] = {(char*) Py_GetProgramFullPath()};
00159   char **argp = argv;
00160   if (!VMDinitialize(&argc, (char ***) &argp, mpienabled)) {
00161     INITERROR;
00162   }
00163 
00164   // XXX this is a hack, and it would be better to tie this into
00165   //     VMDApp more directly at some later point, but the regular
00166   //     VMD startup code is similarly lame, so we'll use it for now.
00167   const char *disp = getenv("VMDDISPLAYDEVICE");
00168   if (!disp) disp = "text";
00169 
00170   int loc[2] = { 50, 50 };
00171   int size[2] = { 400, 400 };
00172   VMDgetDisplayFrame(loc, size);
00173 
00174   VMDApp *app = new VMDApp(1, argv, mpienabled);
00175   app->VMDinit(1, argv, disp, loc, size);
00176 
00177   // read application defaults
00178   VMDreadInit(app);
00179 
00180   // don't read .vmdrc or other user-defined startup files if running
00181   // as a python module because it's too easy for that to cause unintended
00182   // behavior
00183 #if 0
00184   // read user-defined startup files
00185   VMDreadStartup(app);
00186 #endif
00187 
00188   set_vmdapp(app);
00189 
00190   // set my local static
00191   the_app = app;
00192 
00193 #if PY_MAJOR_VERSION >= 3
00194   PyObject *vmdmodule = PyModule_Create(&vmddef);
00195 #else
00196   PyObject *vmdmodule = Py_InitModule3("vmd", VMDAppMethods, vmd_moddoc);
00197 #endif
00198   if (!vmdmodule) {
00199     msgErr << "Failed to import vmd module" << sendmsg;
00200     PyErr_Print();
00201     INITERROR;
00202   }
00203 
00204   int i = 0;
00205   while (py_initializers[i].name) {
00206     const char *name = py_initializers[i].name;
00207     PyObject *module = (*(py_initializers[i].initfunc))();
00208     if (!module) {
00209       msgErr << "Failed to initialize builtin module " << name << sendmsg;
00210       PyErr_Print();
00211       continue;
00212     }
00213 
00214     int retval = PyModule_AddObject(vmdmodule, CAST_HACK name, module);
00215     if (retval || PyErr_Occurred()) {
00216       msgErr << "Failed to import builtin module " << name << sendmsg;
00217       msgErr << "Aborting module import" << sendmsg;
00218       INITERROR;
00219     }
00220     i++;
00221   }
00222 
00223   event_tstate = PyThreadState_Get();
00224 #if defined(VMD_SHARED)
00225   PyOS_InputHook = vmd_input_hook;
00226 #endif
00227 
00228 #if PY_MAJOR_VERSION >= 3
00229   return vmdmodule;
00230 #endif
00231 }
00232 

Generated on Fri Apr 19 02:45:16 2024 for VMD (current) by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002