C API : Creating a Py_Method object from a C function.
I've got a pure python module that parses a certain type of file. It has a load() function that allows a callback function to be passed for getting progress information. In straight python, this works fine. However, I'm now trying to use this from a C++ program. The current flow that I'm trying to get is as follows: C++ calls python interface function, passing a C++ function pointer Python interface function stores C++ function pointer Python interface function generates new Py_Object method pointer pointing to a different C python function. (This different function calls the stored C++ function pointer) Python interface function calls python function Python function calls the python method pointer it was passed C python function then calls the stored C++ function pointer. The problem in this workflow is taking the C python function that I've defined (using the standard "static PyObject *someFunction(PyObject *self, PyObject *args)" method) and converting this into a Py_Object. Any ideas? Py_Method doesn't seem to allow you to generate a new one with your own pointers inside... and I can't see anything else in the docs that might allow me to do this... Thanks for any advice! -- Hugh Macdonald -- http://mail.python.org/mailman/listinfo/python-list
Re: C API : Creating a Py_Method object from a C function.
Thanks Martin - that worked wonderfully For the record (and for anyone searching for this in future), here's the code that worked (with names changed to protect my job...) myPython is the C++/Python interface class containing static methods which pass on calls to the underlying python module. It's not really commented, but if you're trying to do this kind of thing, it should give you what you need. // myPython.h #ifndef ___MYPYTHON_H___ #define ___MYPYTHON_H___ #include using namespace std; typedef struct _object PyObject; typedef void (*loadCallback)(string message, int progress, void *callbackData); staticPyObject *myPython_doLoadCallback(PyObject *self, PyObject *args); class myPython { public: staticlist *loadDetails(string file, loadCallback callbackFunc = NULL, void *callbackData = NULL); staticvoid doLoadCallback(string message, int progress); private: staticPyObject *getResults(char *moduleName, char *functionName, PyObject *args); staticloadCallback callbackFunc; staticvoid *callbackData; }; #endif // ___MYPYTHON_H___ // myPython.cpp #include #include loadCallbackmyPython::callbackFunc = NULL; void*myPython::callbackData = NULL; list *myPython::loadDetails(string file, loadCallback newCallbackFunc, void *newCallbackData) { PyObject *pArgs, *pResult; callbackFunc = newCallbackFunc; callbackData = newCallbackData; PyMethodDef *callbackFunctionDef = new PyMethodDef; callbackFunctionDef->ml_name = "doLoadCallback"; callbackFunctionDef->ml_meth = &myPython_doLoadCallback; callbackFunctionDef->ml_flags = 1; PyObject *pyCallbackFunc = PyCFunction_New(callbackFunctionDef, NULL); pArgs = Py_BuildValue("(sO)", file.c_str(), pyCallbackFunc); pResult = getResults("myPythonModule", "loadDetails", pArgs); if(!pResult) { Py_DECREF(pArgs); return NULL; } if(PyList_Check(pResult)) { // Convert pResult into a list and return that. } return NULL; } PyObject *myPython_doLoadCallback(PyObject *self, PyObject *args) { char *message; int progress; if(!PyArg_ParseTuple(args, "si", &message, &progress)) return NULL; myPython::doLoadCallback(message, progress); return Py_None; } void myPython::doLoadCallback(string message, int progress) { if(callbackFunc) callbackFunc(message, progress, callbackData); } -- http://mail.python.org/mailman/listinfo/python-list
Reading in external file - error checking and line numbers...
I'm writing a tool at the moment that reads in an external file (which can use any Python syntax) At the moment, I'm reading the file in using: scriptLines = open(baseRippleScript).read() exec scriptLines However, if I raise an exception in my main code, in a function that is called from the external script, the stack trace just has: File "", line 8, in ? Ideally, I'd want to be able to avoid throwing exceptions and would like to, from my main code, print out an error that included the script name (easily accessible) and the line number (less easily accessible). Is there a better way of executing an external script that would let me access at any time the line number from the external script that is being executed. More specifically, if a function is called from an external script with an invalid parameter type, I want to be able to flag it accurately to the user Hope this made sense - let me know if I've confused you at all. -- Hugh Macdonald -- http://mail.python.org/mailman/listinfo/python-list
Re: Reading in external file - error checking and line numbers...
Thankyou! That was much easier than I expected. One more thing on a similar note. When raising exceptions, is it possible to remove a few items from the top of the stack trace? My stack trace is looking something like: File "ripple", line 160, in ? File "ripple", line 94, in executeRipple File "test.rip", line 8, in ? dependsOnFrame = new) File "ripple", line 133, in __init__ File "ripple", line 148, in addDependsOnFrame __main__.RippleError: 'Cannot add frame dependency to non frame-based node' I'd like to be able to remove the last two items in the stack so that it just shows the user: File "ripple", line 160, in ? File "ripple", line 94, in executeRipple File "test.rip", line 8, in ? dependsOnFrame = new) __main__.RippleError: 'Cannot add frame dependency to non frame-based node' Unfortunately, I don't know how many 'ripple' stack items there will be... This is why I'd much rather, if I can, do this without exceptions and just be able to print out my own error message with the problem line number marked Or am I asking too much? ;) -- Hugh Macdonald -- http://mail.python.org/mailman/listinfo/python-list
Hacking the scope to pieces
We're starting to version a number of our python modules here, and I've written a small function that assists with loading the versioned modules... A module would be called something like: myModule_1_0.py In anything that uses it, though, we want to be able to refer to it simply as 'myModule', with an environment variable ("MYMODULE_VERSION" - set to "1.0") that defines the version. I've written a module called 'moduleLoader' with the follwing function in: def loadModule(module, version, v = globals()): import compiler loadStr = "import %s_%s as %s" % (module, version.replace(".", "_"), module) eval(compiler.compile(loadStr, "/tmp/%s_%s_errors.txt" % (module, version.replace(".", "_")), "single")) v[module] = vars()[module] The ideal situation with this would be to be able, in whatever script, to have: import moduleLoader moduleLoader.loadModule("myModule", os.getenv("MODULE_VERSION")) However, this doesn't work. The two options that do work are: import moduleLoader moduleLoader.loadModule("myModule", os.getenv("MODULE_VERSION"), globals()) import moduleLoader moduleLoader.loadModule("myModule", os.getenv("MODULE_VERSION")) from moduleLoader import myModule What I'm after is a way of moduleLoader.loadModule working back up the scope and placing the imported module in the main global scope. Any idea how to do this? -- Hugh Macdonald -- http://mail.python.org/mailman/listinfo/python-list
Re: Hacking the scope to pieces
I will take a look! Thanks Skip -- Hugh -- http://mail.python.org/mailman/listinfo/python-list
Re: Hacking the scope to pieces
Maybe I misunderstood what you meant, but I couldn't quite manage to get this one working My initial hopes about __import__() were that I could define it inside my new module (moduleLoader) and, when the module is imported, it could do stuff (like try to hold onto the vars() and globals() from the importing scope). However, I couldn't get it to import... The route I've ended up going (which is just about as simple) is just to return the new module from moduleLoader.loadModule, so my loading code is: import moduleLoader myModule = moduleLoader.loadModule("myModule", os.getenv("MODULE_VERSION")) I've also switched over to using 'inp' for this, rather than creating a compiler string - much nicer Anyway, thanks Skip -- Hugh -- http://mail.python.org/mailman/listinfo/python-list