Hi,
I'm embedding Python 2.2.3 and wxPython 2.4.1 into my C++ program
(which also uses wxWindows). I've run into a problem, though. If I
try to use a wx.ListCtrl, I get this assert:
src\common\event.cpp(797):assert "wxAssertFailure" failed:
wxPyListCtrl should [not] be a window but it is [not]
The line in question:
if ( m_isWindow != IsKindOf(info) )
{
// assert is in here
}
m_isWindow is 1.
The same code works fine when run from the DOS prompt (via
python.exe) as a Python script. In addition, the code works fine
embedded if I use a wx.ListBox instead of wx.ListCtrl.
In my program, the list control is part of a larger dialog involving
sizers. The assert is triggered during the line
"self.SetSizer(sizer)" in the constructor. (I'm assuming it's obvious
what this line is for
When the assert happens, the top bit of the call stack is this:
<just more wxAssert-specific stuff from then up>
wxAssert(int 0, const char * 0x103e6ce0, int 797, const char *
0x103e6cd0, const char * 0x016eb7ec) line 520 + 21 bytes
wxEvtHandler::ProcessEvent(wxEvent & {...}) line 797 + 43 bytes
wxWindow::HandleMove(int 11, int 19) line 4017 + 26 bytes
wxWindow::MSWWindowProc(unsigned int 3, unsigned int 0, long 1245195)
line 2419 + 32 bytes
wxWndProc(HWND__ * 0x001c0784, unsigned int 3, unsigned int 0, long
1245195) line 2372 + 26 bytes
To make matters worse, I'm having some difficulty creating a simple
test program to demonstrate this problem. This program creates a
window, then Python code adds a listbox or listctrl as a child of
that window. With this, I get the wx.ListCtrl assert... but using
wx.ListBox prints a "XXX undetected error" on the console window and
seems to create no list box. (This program is about 120 lines C++ &
20 lines Python, and is appended to the end of this mail.)
I'm really quite lost here -- if anyone has even any vague
suggestions or hints they would be very useful. It is my (Possibly
forlorn) hope that this is a simple problem with an easy fix, though.
Regards,
--Tom
Test program, test1.py:
import wx
def TestFunc(p,x):
print "TestFunc called like TestFunc(\""+x+"\")"
#t=wx.ListBox(parent=p) # <-- this gives the assert
wx.ListBox(parent=p) # <-- this gives "XXX..." on console
def OnExit(frame):#,event):
print "python got OnExit"
def InitMenus(f):
if f.GetMenuBar():
print "already has menu bar"
else:
mb=wx.MenuBar()
mfile=wx.Menu()
mfile.Append(100,"Exit")
wx.EVT_MENU(f,100,OnExit)
mhelp=wx.Menu()
mhelp.AppendSeparator()
mb.Append(mfile,"File")
mb.Append(mhelp,"Help")
f.SetMenuBar(mb)
print "script loaded"
Test program, main.cpp, it's a win32 console program:
#include "pch.h"
#include <stdlib.h>
class TestFrame:
public wxFrame
{
public:
enum {
id_button=1,
};
TestFrame(wxWindow *parent);
void OnButton(wxCommandEvent &);
void OnClose(wxCloseEvent &);
DECLARE_EVENT_TABLE();
};
TestFrame::TestFrame(wxWindow *parent):
wxFrame(parent,-1,"Test",wxDefaultPosition,wxDefaultSize,
wxDEFAULT_FRAME_STYLE)
{
wxButton *b=new wxButton(this,id_button,"Test");
}
void TestFrame::OnButton(wxCommandEvent &) {
PyObject *test=0,*test_dict=0,*test_TestFunc=0,*test_InitMenus=0;
wxPyBeginBlockThreads();
test=PyImport_ImportModule("test1");//new ref
wxASSERT(test);
test_dict=PyModule_GetDict(test);//borrowed ref
wxASSERT(test_dict);
test_TestFunc=PyDict_GetItemString(test_dict,"TestFunc");//b ref
test_InitMenus=PyDict_GetItemString(test_dict,"InitMenus");//b ref
wxASSERT(test_TestFunc);
PyObject *args_TestFunc=PyTuple_New(2);//new ref
PyObject *args_InitMenus=PyTuple_New(1);//new ref
PyTuple_SetItem(args_InitMenus,0,
wxPyMake_wxObject(this));//steals reference
PyTuple_SetItem(args_TestFunc,0,
wxPyMake_wxObject(this));//steals reference
PyTuple_SetItem(args_TestFunc,1,
PyString_FromString("test string"));//steals reference
PyObject *res_TestFunc=PyObject_CallObject(test_TestFunc,
args_TestFunc);//n ref
PyObject *res_InitMenus=PyObject_CallObject(test_InitMenus,
args_InitMenus);//n ref
Py_XDECREF(res_InitMenus);
Py_XDECREF(res_TestFunc);
Py_XDECREF(args_InitMenus);
Py_XDECREF(args_TestFunc);
Py_XDECREF(test);
wxPyEndBlockThreads();
}
void TestFrame::OnClose(wxCloseEvent &) {
printf("bye\n");
this->Destroy();
}
BEGIN_EVENT_TABLE(TestFrame,wxFrame)
EVT_BUTTON(id_button,TestFrame::OnButton)
EVT_CLOSE(TestFrame::OnClose)
END_EVENT_TABLE()
class TestApp:
public wxApp
{
public:
TestApp();
~TestApp();
bool OnInit();
int OnExit();
private:
PyThreadState *pystate_;
};
TestApp::TestApp() {
}
bool TestApp::OnInit() {
Py_IgnoreEnvironmentFlag=0;
Py_Initialize();
PyEval_InitThreads();
wxPyCoreAPI_IMPORT();
pystate_=wxPyBeginAllowThreads();
printf("TestApp::OnInit\n");
TestFrame *tf=new TestFrame(0);
tf->SetSize(640,480);
tf->Show(true);
return true;
}
int TestApp::OnExit() {
printf("TestApp::OnExit\n");
return 0;
}
TestApp::~TestApp() {
wxPyEndAllowThreads(pystate_);
Py_Finalize();
}
IMPLEMENT_APP(TestApp)
int main(int argc,char *argv) {
int r=WinMain(GetModuleHandle(0),0,"",SW_SHOW);
int brk=0;
return r;
}