From: David F. <Dav...@hu...> - 2015-07-01 20:37:45
|
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? |