[C++-sig] Exception second time loaded

Kirsebom Nikolai nikolai.kirsebom at siemens.no
Fri Jun 20 12:11:05 CEST 2003


Hi,
I have some questions:
How do I is it possible to search the archives?

I have defined the PyExecutor class, CString<-->python string converter (see
entry from Ralf W. Grosse-Kunstleve 27th May),
code shown below.
The function "RunPythonViaBoost" is called from the startup function of a
DLL, loaded by the actual application.

If I make use of the 'getit' function, the system runs into an exception the
second time it is started.  The statement in RunStmt method
being executed when the exception occurs is the second statement
(PyRun_String).

The stack-frame in the debugger is:

boost_python_debug.dll!boost::python::throw_error_alread_set() Line 58
DLEPRPythonDLd.dll!boost::python::expect_non_null(_object * x=0x00000000)
Line 45 + 0x8
DLEPRPythonDLd.dll!boost::python::detail::manage_ptr(_object * p=0x00000000,
...) Line 57 + 0x9
DLEPRPythonDLd.dll!boost::python::handle<_object>::handle<_object>(_object *
p=0x00000000) Line 80 + 0x30
DLEPRPythonDLd.dll!PyExecutor::RunStmt(DLEPRInterface * dlepr=0x008be388)
Line 336 + 0x31

Does anyone see what I've done wrong ?

When in the python-shell I write:
import DocuLive
v = DocuLive.getit()

and then closes the shell, what happens to the actual C++ object
(DLEPRInterface) when 'v' goes out of scope ?

THANK YOU FOR ANY HELP.
Nikolai


HERE IS THE CODE

// Wrapper class needed.  If the DLEPRInterface class is used directly,
compiler complains about:
//...\boost_1_30_0\boost\python\object\value_holder.hpp(111): error C2558:
class 'DLEPRInterface' : 
//                         no copy constructor available or copy constructor
is declared 'explicit'
//
// Note that I do not need to construct instances of this class.  The actual
interface object will
// always exist when the dll is loaded, and it provides all information the
dll needs.
//
//The constructors / destructor of DLEPRInteface are:
//
//	DLEPRInterface();
//	DLEPRInterface(const MenuEntry& Menu, CItemView* pView, char
TriggerKey, RootTemplate* MatrixTemplate);
//	DLEPRInterface(CDC* pDC, CItemView* pView, int CurItemIndex, int
Col, int Row, RootTemplate* MatrixTemplate);
//	~DLEPRInterface();
//

class PyDLEPRInterface : public DLEPRInterface
{
public:
	PyDLEPRInterface();
	PyDLEPRInterface(const PyDLEPRInterface& objectSrc);
};

PyDLEPRInterface::PyDLEPRInterface(const PyDLEPRInterface& objectSrc)
{
}

PyDLEPRInterface::PyDLEPRInterface()
{
}

//
////////////////////////////////////////////////////////////////////////////
/////////////
///// EXPOSED INTERFACE
/////////////////////////////////////////////////////////////////

using namespace boost::python;

static PyDLEPRInterface* curr = NULL;

PyDLEPRInterface* getit() {
	return curr;
}

BOOST_PYTHON_MODULE(DocuLive)
{
	def("getit", getit,
return_value_policy<reference_existing_object>())
	;

	class_<PyDLEPRInterface>("DLEPRInterface")
		.def("GetDatabaseName", &PyDLEPRInterface::GetDatabaseName)
		.def("GetDefaultServerName",
&PyDLEPRInterface::GetDefaultServerName)
		.def("IsRubber", &PyDLEPRInterface::IsRubber)

		.def_readonly("RecordId", &PyDLEPRInterface::m_RecordID)
		.def_readonly("Item", &PyDLEPRInterface::m_Item)
		.def_readonly("OriginalItem",
&PyDLEPRInterface::m_OriginalItem)
		.def_readonly("Row", &PyDLEPRInterface::m_Row)
		.def_readonly("Col", &PyDLEPRInterface::m_Col)
		.def_readonly("UserID", &PyDLEPRInterface::m_UserID)
		.def_readonly("m_CurMenuEntry",
&PyDLEPRInterface::m_CurMenuEntry)

        .add_property("DocumentCategory",
make_getter(&PyDLEPRInterface::m_DocumentCategory,
return_value_policy<return_by_value>()))
        .add_property("LookupCategory",
make_getter(&PyDLEPRInterface::m_LookupCategory,
return_value_policy<return_by_value>()))
        .add_property("RecordCategory",
make_getter(&PyDLEPRInterface::m_RecordCategory,
return_value_policy<return_by_value>()))
        .add_property("IconPurpose",
make_getter(&PyDLEPRInterface::m_IconPurpose,
return_value_policy<return_by_value>()))
	;

	class_<MenuEntry>("MenuEntry")
		.add_property("ParamString1",
make_getter(&MenuEntry::ParamString1,
return_value_policy<return_by_value>()))
	;
}

namespace MFCString { namespace {

  struct CString_to_python_str
  {
    static PyObject* convert(CString const& s)
    {
		CString ss = s;
		std::string x = ss.GetBuffer(1000);
      return boost::python::incref(boost::python::object(x).ptr());
    }
  };

  struct CString_from_python_str
  {
    CString_from_python_str()
    {
      boost::python::converter::registry::push_back(
        &convertible,
        &construct,
        boost::python::type_id<CString>());
    }

    static void* convertible(PyObject* obj_ptr)
    {
      if (!PyString_Check(obj_ptr)) return 0;
      return obj_ptr;
    }

    static void construct(
      PyObject* obj_ptr,
      boost::python::converter::rvalue_from_python_stage1_data* data)
    {
      const char* value = PyString_AsString(obj_ptr);
      if (value == 0) boost::python::throw_error_already_set();
      void* storage = (
 
(boost::python::converter::rvalue_from_python_storage<CString>*)data)->stora
ge.bytes;
      new (storage) CString(value);
      data->convertible = storage;
    }
  };

  void init_module()
  {
    using namespace boost::python;

    boost::python::to_python_converter<
      CString,
      CString_to_python_str>();

    CString_from_python_str();
  }
}} // namespace MFCString::<anonymous>

BOOST_PYTHON_MODULE(MFC)
{
	class_<CRect>("CRect")
		.def_readwrite("bottom", &CRect::bottom)
		.def_readwrite("top", &CRect::top)
		.def_readwrite("right", &CRect::right)
		.def_readwrite("left", &CRect::left)
		.def("Height", &CRect::Height)
		.def("Width", &CRect::Width)
	;

	class_<CPoint>("CPoint")
		.def_readwrite("x", &CPoint::x)
		.def_readwrite("y", &CPoint::y)
	;
}

BOOST_PYTHON_MODULE(CString)
{
  MFCString::init_module();
}

////////////////////////////////////////////////////////////////////////////
////////
/// PYTHON EXECUTOR CLASS
//////////////////////////////////////////////////////////

class PyExecutor
{
public:
	PyExecutor();
	~PyExecutor();
	CString RunStmt(DLEPRInterface * dl);
	PyObject * MainNamespace;
};

PyExecutor::PyExecutor()
{
	    // Register the module with the interpreter
    if (PyImport_AppendInittab("DocuLive", initDocuLive) == -1)
        throw std::runtime_error("Failed to add DocuLive to the
interpreter's builtin modules");

    if (PyImport_AppendInittab("MFC", initMFC) == -1)
        throw std::runtime_error("Failed to add MFC to the interpreter's
builtin modules");

    if (PyImport_AppendInittab("CString", initCString) == -1)
        throw std::runtime_error("Failed to add CString to the interpreter's
builtin modules");
	
	Py_Initialize();

	boost::python::handle<> main_module(borrowed(
PyImport_AddModule("__main__")));
	boost::python::handle<> main_namespace(borrowed(
PyModule_GetDict(main_module.get()) ));
	MainNamespace = main_namespace.get();
}

PyExecutor::~PyExecutor()
{
	Py_Finalize();
}

CString PyExecutor::RunStmt(DLEPRInterface * dlepr)
{
	curr = (PyDLEPRInterface *)dlepr;  //<<<--- Global variable, 

	boost::python::handle<> result(PyRun_String(
		"import sys\n"
		"import wxPython.lib.PyCrust.PyShellApp\n"
		"wxPython.lib.PyCrust.PyShellApp.main()\n"
		"valx = 'done'\n",
		Py_file_input, MainNamespace, MainNamespace));

	result.reset();

	PyObject *p = PyRun_String("valx", Py_eval_input, MainNamespace,
MainNamespace);

	result.release();

	if (p != 0) {
		char *s;
		int i = PyArg_Parse(p, "s", &s);
		return _T(s);
	} else {
		return _T("NULL");
	}
}

UINT ThreadFunc(LPVOID pParam)
{
	static PyExecutor *x = NULL;
	
	if (x == NULL) {
		x = new PyExecutor();
	}
	CString v = x->RunStmt((DLEPRInterface *)pParam);
	return 0;
}

void RunPythonViaBoost(DLEPRInterface *pInterface, int Modeless)
{
	CWinThread * pThread = AfxBeginThread(ThreadFunc, pInterface);
	HANDLE hThread = pThread->m_hThread;
	if (Modeless == 0)
		::WaitForSingleObject(hThread, INFINITE);
}




More information about the Cplusplus-sig mailing list