From: Barry S. <ba...@ba...> - 2015-08-05 17:46:06
|
Py::Module canot import a module. It can only hold a ref to an already imported module. Becuase of the complexity of import in python its easiest to use PyRun_SimpleString. PyRun_SimpleString( "import foo.bar" ); Barry p.s. I did reply a while ago but sf.net's FUBAR dropped the mail. On 01/07/2015 21:37, David Fox wrote: > I’m trying to take the example from section 1.3 of the python > embedding documentation > (https://docs.python.org/3/extending/embedding.html#pure-embedding), > with usage > > Usage: call pythonfile funcname [args] > > > and rewrite it using CXX (with some extra diagnostics, and modified to > use str() so it handles functions which return anything, not just long): > > #include <Python.h> > #include <CXX/Objects.hxx> > #include <string> > #include <iostream> > > int > main(int argc, char *argv[]) > { > int i; > > if (argc < 3) { > fprintf(stderr,"Usage: call pythonfile funcname [args]\n"); > return 1; > } > > std::string name(argv[1]); > > std::string funcname(argv[2]); > Py_Initialize(); > std::string status; > try { > Py::Module module(name); > > std::cout << module.repr() << '\n'; > if (!module.isTrue()) { > std::cout << "module was null/false\n"; > throw Py::Exception(); > } > status = "finding function " + funcname; > if (!module.hasAttr(funcname)) { > std::cout << "function " << funcname + " not found\n"; > throw Py::Exception(); > } > Py::Object obj = module.getAttr(funcname); > if (!obj.isTrue()) { > std::cout << "function was null/false\n"; > throw Py::Exception(); > } > if (!obj.isCallable()) { > std::cout << "got function but not callable?\n"; > throw Py::Exception(); > } > status = "casting function " + funcname; > Py::Callable func(obj); > status = "creating arg tuple"; > Py::Tuple fargs(argc - 3); > status = "filling arg tuple"; > for (i = 0; i < argc - 3; ++i) { > fargs[i] = Py::Long(atoi(argv[i + 3])); > } > status = "calling"; > Py::Object res(func.apply(fargs)); > // status = "converting to long"; > // Py::Long v(res); > std::cout << "Result of call: " << res.str() << '\n'; > } catch (const Py::Exception &) { > std::cout << "call failed with status " << status << '\n'; > } > > Py_Finalize(); > return 0; > } > > > The original version compiles and runs correctly. For example > > $ ./call math exp 2 > Result of call: 7 > > $ PYTHONPATH=`pwd` ./call multiply multiply 2 3 > Will compute 2 times 3 > Result of call: 6 > > My CXX version works as long as the module I specify is sys or os: > > ./pure_cxx sys exc_info > <module 'sys' (built-in)> > Result of call: (None, None, None) > > $ ./pure_cxx os getcwd > <module 'os' from > '/Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/os.py'> > Result of call: /Users/dfox/python/test/embed > > but if I use math or a custom module, it fails to find the function in > the given module: > > $ ./pure_cxx math exp 2 > <module 'math'> > function exp not found > call failed with status finding function exp > > > $ PYTHONPATH=`pwd` ./pure_cxx multiply multiply 2 3 > <module 'multiply'> > function multiply not found > call failed with status finding function multiply > > > Oddly, it doesn’t raise an exception when I create the Py::Module, but > that module seems to be a dummy module, with the right name and a few > other attributes all with value None, as can be seen by converting the > module to a Py::List and iterating over it: > > 0 __name__ : math > > 1 __loader__ : None > > 2 __spec__ : None > > 3 __package__ : None > > 4 __doc__ : None > > > Any idea what I’m doing wrong? > > > ------------------------------------------------------------------------------ > Don't Limit Your Business. Reach for the Cloud. > GigeNET's Cloud Solutions provide you with the tools and support that > you need to offload your IT needs and focus on growing your business. > Configured For All Businesses. Start Your Cloud Today. > https://www.gigenetcloud.com/ > > > _______________________________________________ > CXX-Users mailing list > CXX...@li... > https://lists.sourceforge.net/lists/listinfo/cxx-users |