[C++-sig] copy constructors and multiple instances

Josh Stratton strattonbrazil at gmail.com
Sat Sep 3 05:27:18 CEST 2011


Here's a really short example of what I don't understand.  Basically I
can setup the python function to accept shared pointers, but can I
setup it to also use normal pointers?  In the example code attached,
if I uncomment scene->sendYourselfToPython(); it fails because it's
using "this" as the scene pointer.

Error in Python: <type 'exceptions.TypeError'>: No to_python
(by-value) converter found for C++ type: Scene

So it appears to only work for shared pointers at this point.  Can I
also get it to work with "this" at the same time?  Jim pointed me to
"enable_shared_from_this" as a way for creating a shared pointer
object, which makes sense from the docs of how to do it, but I was
wondering if I necessarily NEED to send it down as a shared pointer.

Thanks

http://dpaste.com/607969/

OR

#include <iostream>

#include <boost/python.hpp>
#include <boost/python/class.hpp>
#include <boost/python/module.hpp>
#include <boost/python/def.hpp>

using namespace boost::python;

object pyMainModule;
object pyMainNamespace;

#define EXAMPLE_PY_FUNCTION \
  "from scene import Scene\n" \
  "class Foo(object):\n" \
  "  @staticmethod\n" \
  "  def processFile(scene, filename):\n" \
  "    print('here')\n"

std::string parse_python_exception();

class Scene
{
public:
  void sendYourselfToPython()
  {
    try {
      object ignored = exec(EXAMPLE_PY_FUNCTION, pyMainNamespace);
      object processFileFunc = pyMainModule.attr("Foo").attr("processFile");
      processFileFunc(this, "test.txt");
    } catch (boost::python::error_already_set const &) {
      std::string perror = parse_python_exception();
      std::cerr << "Error in Python: " << perror << std::endl;
    }
  }
};
typedef boost::shared_ptr<Scene> SceneP;

BOOST_PYTHON_MODULE(scene)
{
  class_<Scene, boost::noncopyable>("Scene");
}

main(int argc, char**argv)
{
  std::cout << "starting program..." << std::endl;

  Py_Initialize();
  pyMainModule = import("__main__");
  pyMainNamespace = pyMainModule.attr("__dict__");

  boost::python::register_ptr_to_python< boost::shared_ptr<Scene> >();
  PyImport_AppendInittab("scene", &initscene);

  SceneP scene(new Scene());
  scene->sendYourselfToPython(); // confused here

  try {
    object ignored = exec(EXAMPLE_PY_FUNCTION, pyMainNamespace);
    object processFileFunc = pyMainModule.attr("Foo").attr("processFile");
    processFileFunc(scene, "test.txt");
  } catch (boost::python::error_already_set const &) {
    std::string perror = parse_python_exception();
    std::cerr << "Error in Python: " << perror << std::endl;
  }
}


// taken from http://thejosephturner.com/blog/2011/06/15/embedding-python-in-c-applications-with-boostpython-part-2/
namespace py = boost::python;
std::string parse_python_exception() {
    PyObject *type_ptr = NULL, *value_ptr = NULL, *traceback_ptr = NULL;
    PyErr_Fetch(&type_ptr, &value_ptr, &traceback_ptr);
    std::string ret("Unfetchable Python error");
    if (type_ptr != NULL) {
        py::handle<> h_type(type_ptr);
        py::str type_pstr(h_type);
        py::extract<std::string> e_type_pstr(type_pstr);
        if(e_type_pstr.check())
            ret = e_type_pstr();
        else
            ret = "Unknown exception type";
    }

    if (value_ptr != NULL) {
        py::handle<> h_val(value_ptr);
        py::str a(h_val);
        py::extract<std::string> returned(a);
        if(returned.check())
            ret +=  ": " + returned();
        else
            ret += std::string(": Unparseable Python error: ");
    }

    if (traceback_ptr != NULL) {
        py::handle<> h_tb(traceback_ptr);
        py::object tb(py::import("traceback"));
        py::object fmt_tb(tb.attr("format_tb"));
        py::object tb_list(fmt_tb(h_tb));
        py::object tb_str(py::str("\n").join(tb_list));
        py::extract<std::string> returned(tb_str);
        if(returned.check())
            ret += ": " + returned();
        else
            ret += std::string(": Unparseable Python traceback");
    }
    return ret;
}


On Fri, Sep 2, 2011 at 2:15 PM, Dave Abrahams <dave at boostpro.com> wrote:
>
> on Fri Sep 02 2011, Josh Stratton <strattonbrazil-AT-gmail.com> wrote:
>
>> Well, right now I'm just passing "this" from inside the scene object,
>> so does that need to be wrapped in a shared pointer?
>
> That's a pretty vague description of what you're doing, so it's hard to
> say.  I suggest you reduce your question to a minimal case that doesn't
> involve any of your domain-specific stuff.  Then it will be easy to
> answer.
>
>>
>> On Fri, Sep 2, 2011 at 12:19 PM, Dave Abrahams <dave at boostpro.com> wrote:
>>>
>>> on Thu Sep 01 2011, Jim Bosch <talljimbo-AT-gmail.com> wrote:
>>>
>>>> boost::python::register_ptr_to_python< boost::shared_ptr<Scene> >();
>>>>
>>>> This allows you to return shared_ptr to Python, but because a
>>>> boost::shared_ptr can use an arbitrary deleter, Boost.Python can
>>>> convert any wrapped Scene object (even one that doesn't hold a
>>>> shared_ptr<Scene>) into a shared_ptr<Scene> with correct reference
>>>> counting.
>>>
>>> I might have forgotten by now, but I don't think you need to register
>>> shared_ptr, and I don't think the above will have any effect.  IIRC I
>>> made sure shared_ptr support "just works" out-of-the-box.
>>>
>>> --
>>> Dave Abrahams
>>> BoostPro Computing
>>> http://www.boostpro.com>
>>> _______________________________________________
>>> Cplusplus-sig mailing list
>>> Cplusplus-sig at python.org
>>> http://mail.python.org/mailman/listinfo/cplusplus-sig>
>
> --
> Dave Abrahams
> BoostPro Computing
> http://www.boostpro.com
>
> _______________________________________________
> Cplusplus-sig mailing list
> Cplusplus-sig at python.org
> http://mail.python.org/mailman/listinfo/cplusplus-sig
>


More information about the Cplusplus-sig mailing list