#include <python.h>
int main() {
Py_Initialize();
FILE *p = fopen("test.py", "r");
PyRun_SimpleFile(p, "test.py");
fclose(p);
if (Py_IsInitialized())
Py_Finalize();
return 0;
}
If you are using Boost.Python, tell me how are you actually calling python files within your application.
It just crashes.
[edited by - ffx on August 8, 2003 3:13:19 PM]
(Yet) another python problem
Why doesn't this work? Can anybody help?
So... Muira Yoshimoto sliced off his head, walked 8 miles, and defeated a Mongolian horde... by beating them with his head?
Documentation? "We are writing games, we don't have to document anything".
Documentation? "We are writing games, we don't have to document anything".
I dont see your problem, but I can share with you how I call Python.
In my engine, I use only the Very High Level Embedding to call python. I wrap PyRun_SimpleString myself to provide error checking, but that is unnecessary here.
In other words, I have a class written in Python that calls out to other scripts.
Then, in the scripts, I do
where engine is a static python extension module (this is where I''m having trouble myself, but I know it can be done).
No boost.python necessary until the static extension part.
HTH,
Dustin
In my engine, I use only the Very High Level Embedding to call python. I wrap PyRun_SimpleString myself to provide error checking, but that is unnecessary here.
PyRun_SimpleString("import sys");PyRun_SimpleString("sys.path.append("./scripts");PyRun_SimpleString("import scheduler");PyRun_SimpleString("secheduler.load(''ascript'')");while (true) PyRun_SimpleString("scheduler.update()");
In other words, I have a class written in Python that calls out to other scripts.
Then, in the scripts, I do
import enginedef main() ... yield None #all my scripts have a generator function called main
where engine is a static python extension module (this is where I''m having trouble myself, but I know it can be done).
No boost.python necessary until the static extension part.
HTH,
Dustin
I beleive that's a bug in Python. You have to use the multi-threaded dll runtime.
edit:
Alternatively you could load the whole script into a string and use PyRun_SimpleString.
[edited by - M_R_Ducs on August 8, 2003 4:14:38 PM]
edit:
Alternatively you could load the whole script into a string and use PyRun_SimpleString.
[edited by - M_R_Ducs on August 8, 2003 4:14:38 PM]
Whoa, you guys really do use the high level stuff huh? If you want to have more control over your scripts, like I do, then use more lower level functions like so (this is my actual in-engine script class, that pretty much wraps all this good stuff up for me). First the header:
And now the implementation:
And I''m sorry if it''s not really legible, the gamedev.net parser likes to take out empty lines... But as you can see, I ''import'' the module, and then grab it''s dictionary. This way, you know all the functions in that particular module. I originally had it such that I scanned through a directory and added all functions to a list, but then I realized you can have functions named the same with same arguments, but just different script files, so I trashed the idea... But here''s an example of the script object working. This is where I grab an API from each of the scripts so that I can call them without regard to which file or whatnot.
Oh yeah, and I couldn''t tell you why you''re codes not working. I just checked the API docs and it appears to be correct. Why not test your file pointer to make sure it''s valid? Technically, I''m assuming the test.py file is in the same directory as the workspace?
Chris Pergrossi
My Realm | "Good Morning, Dave"
#ifndef _SCRIPT_H_#define _SCRIPT_H_#include "unknown.h"#include "singleton.h"#ifndef _GHOST_MODULE_PATH_#define _GHOST_MODULE_PATH_ "C:/Developer/Scripts/"#endiftypedef class boost::python::object BstObject;typedef class boost::python::handle<> BstHandle;enum KPyObjectType{ PYTYPE_INVALID = 0, PYTYPE_FUNCTION, PYTYPE_VARIABLE};#define CallScript PyObject_CallFunctionclass GstScript : public GstUnknown{private: // the module object BstObject module, dict; // the module name (without path or extension) char name[ 32 ]; // declare our manager as a friend friend class GstScriptMgr; // the bind function void Bind( BstObject& module, char* name );public: // default constructor GstScript() {} // gets an object (could be function or variable) PyObject* Get( char* object ); // gets the script''s name const char* getName() { return name; } // checks what sort of object is under this name KPyObjectType Type( char* object ); // operator overloads PyObject* operator[]( char* variable );};class GstScriptMgr : public GstSingleton< GstScriptMgr >{private: // loads the Python interpreter bool LoadPython( char* modPath ); // frees the Python interpreter bool FreePython();public: // default constructor GstScriptMgr( char* modPath = _GHOST_MODULE_PATH_ ); // destructor ~GstScriptMgr(); // retrieves a script bool LoadModule( char* modName, GstScript& script );};// pre-definition of the ''script'' Python moduleextern "C" { extern void __declspec(dllexport) initscript();}#endif
And now the implementation:
#ifdef _DEBUG#undef _DEBUG#define _ISDEBUG_#include <Python.h>#include <Boost/Python.h>#else#include <Python.h>#include <Boost/Python.h>#endif#ifdef _ISDEBUG_#pragma warning( disable : 4005 )#define _DEBUG#endif#include <iostream.h>#include <stdarg.h>#include "types.h"#include "hash.h"#include "script.h"#pragma comment( lib, "boost_python.lib" )using namespace boost::python;BOOST_PYTHON_MODULE(script){ class_<GstScript>( "KScript" ) .def( "Get", &GstScript::Get ) .def( "Type", &GstScript::Type ) ; class_<GstScriptMgr>( "KScriptMgr", no_init ) .def( "LoadModule", &GstScriptMgr::LoadModule ) ; def( "get", &GstScriptMgr::get, return_value_policy< reference_existing_object >() );}// the bind functionvoid GstScript :: Bind( BstObject& mod, char* str ){ // copy the passed objects into this variable module = mod; strcpy( name, str ); // get the dictionary (borrowed reference!) dict = BstObject( BstHandle( boost::python::borrowed( PyModule_GetDict( module.ptr() ) ) ) );}// calls a functionPyObject* GstScript :: Get( char* obj ){ // get the requested function (borrowed!) PyObject* tmp = PyDict_GetItemString( dict.ptr(), obj ); // check if it''s valid if( !tmp ) { PyErr_Print(); // Log Error Here cout << "Couldn''t Find The Object: " << obj << "\n"; cout.flush(); } // it''s valid return tmp;}// checks what sort of object is under this nameKPyObjectType GstScript :: Type( char* object ){ PyObject* ptr = Get( object ); if( !dict || !module || !ptr ) return PYTYPE_INVALID; if( PyCallable_Check( ptr ) ) return PYTYPE_FUNCTION; return PYTYPE_VARIABLE;}// operator overloads////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// loads the Python interpreterbool GstScriptMgr :: LoadPython( char* modPath ){ // initialize the interpreter Py_Initialize(); // copy the script location into Python char buffer[ 128 ]; sprintf( buffer, "sys.path.append(''%s'')", modPath ); PyRun_SimpleString( "import sys" ); PyRun_SimpleString( buffer ); sprintf( buffer, "sys.path.append(''%s'' + ''Events/'')", modPath ); PyRun_SimpleString( buffer ); // return success return true;}// frees the Python interpreterbool GstScriptMgr :: FreePython(){ // free the interpreter Py_Finalize(); return true;}// default constructorGstScriptMgr :: GstScriptMgr( char* modPath ){ bool res; // load the python interpreter res = LoadPython( modPath ); assert( res && "Unable To Start The Python Interpreter" );}// destructorGstScriptMgr :: ~GstScriptMgr(){ bool res; // free the Python interpreter res = FreePython(); assert( res && "Unable To Free Python Interpreter" );}// retrieves a scriptbool GstScriptMgr :: LoadModule( char* modName, GstScript& script ){ PyObject* ptr = PyImport_Import( PyString_FromString( modName ) ); if( !ptr ) { PyErr_Print(); // print an error message cout << "Couldn''t GstScriptMgr::LoadModule() The Requested Module ''" << modName << "''\n"; cout.flush(); return false; } BstObject& mod = BstObject( BstHandle( ptr ) ); script.Bind( mod, modName ); return true;}
And I''m sorry if it''s not really legible, the gamedev.net parser likes to take out empty lines... But as you can see, I ''import'' the module, and then grab it''s dictionary. This way, you know all the functions in that particular module. I originally had it such that I scanned through a directory and added all functions to a list, but then I realized you can have functions named the same with same arguments, but just different script files, so I trashed the idea... But here''s an example of the script object working. This is where I grab an API from each of the scripts so that I can call them without regard to which file or whatnot.
// load the APIscriptAPI.InitActive = (void*) Script.Get( "InitActive" );scriptAPI.InitPriority = (void*) Script.Get( "InitPriority" );scriptAPI.Create = (void*) Script.Get( "Create" );scriptAPI.Start = (void*) Script.Get( "Start" );scriptAPI.Update = (void*) Script.Get( "Update" );scriptAPI.Stop = (void*) Script.Get( "Stop" );scriptAPI.Destroy = (void*) Script.Get( "Destroy" );// get the default values from the scriptactive = extract<u16>( BstObject( BstHandle( CallScript( (PyObject*) scriptAPI.InitActive, "" ) ) ) );priority = extract<u16>( BstObject( BstHandle( CallScript( (PyObject*) scriptAPI.InitPriority, "" ) ) ) );
Oh yeah, and I couldn''t tell you why you''re codes not working. I just checked the API docs and it appears to be correct. Why not test your file pointer to make sure it''s valid? Technically, I''m assuming the test.py file is in the same directory as the workspace?
Chris Pergrossi
My Realm | "Good Morning, Dave"
Chris PergrossiMy Realm | "Good Morning, Dave"
Thanks c t o a n, I''ll try that. Whole Python API documentation is pretty good but it gives you no real examples of embeding. Also, there are no real examples of using Boost.Python, just detailed docs.
thedustbustr: I see where you are going, but when you execute one PyRun_SimpleString, the following one doesn''t know anything about it. Maybe I should concatenate more lines into one.
thedustbustr: I see where you are going, but when you execute one PyRun_SimpleString, the following one doesn''t know anything about it. Maybe I should concatenate more lines into one.
So... Muira Yoshimoto sliced off his head, walked 8 miles, and defeated a Mongolian horde... by beating them with his head?
Documentation? "We are writing games, we don't have to document anything".
Documentation? "We are writing games, we don't have to document anything".
"thedustbustr: I see where you are going, but when you execute one PyRun_SimpleString, the following one doesn't know anything about it. Maybe I should concatenate more lines into one. "
wrong. As far as I can tell, PyRun_SimpleString is like running a command in the python interpreter. Not only that, but take this for example:
and now every python script that does 'import katana' can access 'katana.foo'. It sounds like it wouldnt work, but try it, its great. I believe this works because katana is a static built-in (like 'sys'), I expect it would not work (and if it does, thats a security problem) for a normal pure python module (but I've never tried).
Now that I got my static python extension module working (thanks ctoan!) everything is beautiful. I use none of the python api functions except for PyRun_SimpleString, PyErr_Occurred, and PyErr_Print (and a whole bunch of boost.python wrapper stuff). Then I have a script handler class written in Python that gives each script execution time using generators (sort of like threads but, imo, much much better (simpler, more control, none of that typical threadsafe hassle)). And now that I fixed my static extension module I'm flying my camera around a 3d terrain mesh using bezier curves and circular orbits and its awesome.
The boost.python documentation is not for the faint of heart (they were way over my head), but at the end of each section there is usually an example (with c++ and python code), and the tutorial is great. For python embedding docs, python ships with a great tutorial (its seperate from the api reference).
cameras following Bezier curves are the shit, let me tell you
Enough ranting.
Dustin
[edited by - thedustbustr on August 10, 2003 7:33:57 PM]
wrong. As far as I can tell, PyRun_SimpleString is like running a command in the python interpreter. Not only that, but take this for example:
PyRun_SimpleString("import katana"); //thats my static modulePyRun_SimpleString("katana.foo=42"); //create a new variable in katana module namespace
and now every python script that does 'import katana' can access 'katana.foo'. It sounds like it wouldnt work, but try it, its great. I believe this works because katana is a static built-in (like 'sys'), I expect it would not work (and if it does, thats a security problem) for a normal pure python module (but I've never tried).
Now that I got my static python extension module working (thanks ctoan!) everything is beautiful. I use none of the python api functions except for PyRun_SimpleString, PyErr_Occurred, and PyErr_Print (and a whole bunch of boost.python wrapper stuff). Then I have a script handler class written in Python that gives each script execution time using generators (sort of like threads but, imo, much much better (simpler, more control, none of that typical threadsafe hassle)). And now that I fixed my static extension module I'm flying my camera around a 3d terrain mesh using bezier curves and circular orbits and its awesome.
The boost.python documentation is not for the faint of heart (they were way over my head), but at the end of each section there is usually an example (with c++ and python code), and the tutorial is great. For python embedding docs, python ships with a great tutorial (its seperate from the api reference).
cameras following Bezier curves are the shit, let me tell you
Enough ranting.
Dustin
[edited by - thedustbustr on August 10, 2003 7:33:57 PM]
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement