需要在编译成dll或.o的时候,加入编译选项-DSQLITE_THREADSAFE=2
gcc -c sqlite3.c -o sqlite3.dll -DSQLITE_THREADSAFE=2
http://sqlite.org/threadsafe.html
To see a world in a grain of sand.
And a heaven in a wild flower
Hold infinity in the palm of your hand.
And eternity in an hour
一花一世界
一沙一天堂
掌中握无限
霎那成永恒
星期四, 八月 20, 2009
星期三, 八月 19, 2009
gcc编译 vtable undefined reference错误
通过在基类中定义虚函数virtual,然后要求子类覆盖,从而实现多态是常见技术
但是这种定义,在link的时候出现 vtable ..undefined reference to 的错误,原因是gcc实现
C++规范的时候的问题,解决这个问题,是需要必须顶一个空的virtual,这样造成了,编译器
检查强迫子类覆盖的失效,非常的不爽。virtual myfunction (){}; 语法来规避错误
有人建议使用 virtual myfunction ()=0;但没有成功
http://gcc.gnu.org/faq.html#vtables
但是这种定义,在link的时候出现 vtable ..undefined reference to 的错误,原因是gcc实现
C++规范的时候的问题,解决这个问题,是需要必须顶一个空的virtual,这样造成了,编译器
检查强迫子类覆盖的失效,非常的不爽。virtual myfunction (){}; 语法来规避错误
有人建议使用 virtual myfunction ()=0;但没有成功
http://gcc.gnu.org/faq.html#vtables
class Port { private: char *brand; char style[20]; // i.e. tawny, ruby, vintage int bottles; public: Port(const char *br = "none", const char *st = "none", int b = 0); Port(const Port &p); // copy constructor virtual ~Port() { delete [] brand;} Port & operator=(const Port &p); Port & operator+=(int b); Port & operator-=(int b); int BottleCount() const {return bottles;} virtual void Show() const; friend ostream &operator<<(ostream &os, const Port &p); }; class VintagePort : public Port { private: char * nickname; // i.e. The Noble, or Old Velvet, etc. int year; // vintage year public: VintagePort(); VintagePort(const char *br, int b, const char *nn, int y); VintagePort(const VintagePort &vp); ~VintagePort() {delete [] nickname;} void Show() const; friend ostream & operator<<(ostream &os, const VintagePort & vp); };
星期六, 八月 15, 2009
wxWidgets RTTI 使用
为了让使用类新Java class.forName,动态载入class的方法,计划用指定class 名字,
然后再c++中载入该类.经过研究,发现wxWidgets支持RTTI。
首先需要在编译选项中加入wxUSE_EXTENDED_RTTI选项,
然后使用类似下面的方法:
#ifndef AIBASE_H
#define AIBASE_H
#include
#include
class AIBase:public wxObject,public wxThread
{
public:
AIBase();
~AIBase();
virtual void *Entry();//logic code in here
virtual void OnExit();
protected:
private:
DECLARE_DYNAMIC_CLASS(AIBase);
};
#endif // AIBASE_H
注意类必须继承来自wxObject,而且必须加入public的修饰符。
否则继承自AIBase的子类会出现,
is an inaccessible base of 'wxObject'
注意: DECLARE_DYNAMIC_CLASS用来class定义头文件中
IMPLEMENT_DYNAMIC_CLASS用在实现的CPP 代码文件中
可以参看:
http://wiki.wxwidgets.org/RTTI
然后再c++中载入该类.经过研究,发现wxWidgets支持RTTI。
首先需要在编译选项中加入wxUSE_EXTENDED_RTTI选项,
然后使用类似下面的方法:
#ifndef AIBASE_H
#define AIBASE_H
#include
#include
class AIBase:public wxObject,public wxThread
{
public:
AIBase();
~AIBase();
virtual void *Entry();//logic code in here
virtual void OnExit();
protected:
private:
DECLARE_DYNAMIC_CLASS(AIBase);
};
#endif // AIBASE_H
注意类必须继承来自wxObject,而且必须加入public的修饰符。
否则继承自AIBase的子类会出现,
is an inaccessible base of 'wxObject'
注意:
IMPLEMENT_DYNAMIC_CLASS用在实现的CPP 代码文件中
http://wiki.wxwidgets.org/RTTI
星期三, 八月 05, 2009
wxWidgets动态事件表
wxWidgets动态事件表
使用动态事件映射方法的原因,可能是你想在程序运行的不同时刻使用不同的映射关系,或者因为你使用的那种语言(例如python)不支持静态映射,或者仅仅是因为你更喜欢动态映射。因为动态映射的方法可以使你更精确的控制事件表的细节,你甚至可以单独的将事件表中的某一个条目在运行期打开或者关闭,而前面说的PushEventHandler和PopEventHandler的方法只能针对整个事件表进行处理。除此以外,动态事件处理还允许你在不同的类之间共享事件函数。
——《WxWidgets跨平台GUI开发》
导言
在wxWidgets中,相对于静态事件表那种僵死并且不知其所以然的方法,我更喜欢动态事件表,亲自Connect,还可以随时Disconnect。
但是,在写动态事件表时,会遇到一个问题,wxWidgets的官方文档中的事件处理部份,对于静态事件表所需的各种事件类型的宏叙述详尽,却对动态事件表所需的事件类型语焉不详,这给我们的使用带来了麻烦。需要的知识一方面零星分布于wx文档中,另一方面被冗长的代码掩映在
大部份写GUI常用的wx类(包括窗口、对话框、控件)都继承于三个类:wxWindowwx、wxEvtHandler、wxObject。因此,大多数情况下,这三个类的成员函数是我们可以顺手牵过来用的。动态事件表的使用中,最为重要的函数Connect和Disconnect就是 wxEvtHandler的成员函数,我们可以牵过来给我们手头这个要处理事件的wx类用。
先看看官方文档里对Connect函数的介绍(我对其进行了翻译、精简,有时,为了解释的明晰,作一些补充说明):
#TRANSLATE BEGIN
wxEvtHandler::Connect
Connect函数被重载了三次,各有各的用途。
第一个版本:范围捕杀 ( [id, lastid] 且 eventType)
void Connect(int id, int lastId, wxEventType eventType, wxObjectEventFunction function, wxObject* userData = NULL, wxEvtHandler* eventSink = NULL)
第二个版本:精确狙击(id 且 eventType)
void Connect(int id, wxEventType eventType, wxObjectEventFunction function, wxObject* userData = NULL, wxEvtHandler* eventSink = NULL)
第三个版本:分门别类 (仅 eventType)
void Connect(wxEventType eventType, wxObjectEventFunction function, wxObject* userData = NULL, wxEvtHandler* eventSink = NULL)
该函数动态地将所给事件处理函数 与 EventHandler、ID 甚至事件类型联系起来。这是静态事件表的一种替代选择。
按:EventHandler直译为事件处理器,或可译为“事件手柄”(生动地模仿句柄)?后文使用“事件手柄”。
参数意义:
id
你要和事件处理函数联系起来的ID(可以是窗口ID、菜单ID、控件ID)。对于没有这个参数的重载版本,id被默认设为 wxID_ANY。
当和lastid连用时,表达的是一个ID范围,即大小介于id和last id之间的所有ID,都会被Connect函数与事件处理函数联系起来。
按:实在没必要连“ID”都译成“标识符”……其实看技术文档时,我最头痛的是一堆汉字堆在那里,包括看数学书时……
lastId
参见id中的介绍。
eventType
你要和事件处理函数联系起来的Event Type。按:Event Type直译为“事件类型”并不恰当,因为事件类型是指形如wxMouseEvent这样的东西,而这里所指,是形如wxEVT_MOTION这样的东西。准确地说,应该称之为“事件标识符”或“事件ID”。下文使用“事件ID”。一个事件类型里,会有若干事件ID,比wxMouseEvent里除了wxEVT_MOTION,还有wxEVT_LEFT_DOWN等等等事件ID。 因此可以把事件ID作为对事件类型的一个细分。
function
事件处理函数。注意这个函数应当被显式转换为正确的类型。对于类型为wxFooEvent的事件,转换使用宏wxFooEventHandler。
userData
你要和事件表项联系起来的数据。(暂时我还不知道这个有什么用)
eventSink
告诉Connect函数,你要调用的事件处理函数是谁的成员函数。如果该参数为 NULL, 那么Connect函数将使用this指针 。按:正是这个参数允许了我们在不同类中共享事件处理函数。
例子:frame->Connect( wxID_EXIT, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(MyFrame::OnQuit) );对例子的解释:wxID_EXIT是之前赋给了某一个菜单项的ID。当该菜单被选择时,会产生一个ID为wxEVT_COMMAND_MENU_SELECTED的事件。因此MyFrame::OnQuit在被显式转换为wxCommandEventHandler型的“事件手柄”之后,被Connect拉过来处理该事件。 #TRANSLATE END
就不再翻译Disconnect函数的文档了,因为除了函数名不同,它的所有参数和Connect是一模一样的。它的用途就是断开Connect所建立起来的联系。
实践中写事件处理的时候,通常使用的是Connect的后两种重载版本。参数userData和eventSink的使用是比较少的,而且也有默认值,一般不去理它就可以了。
参数id是你赋给产生了这个事件的窗口、菜单或控件的,你自己心里是清楚的。问题顶多是,你需要使用系统默认的那些ID(比如上面例子里的 wxID_EXIT),而你不知道哪个还哪个。那些ID的列表在官方文档里是有的,不过为了本文作为手册的完整性,将在本文最后给出。
有时是不需要id的,比如鼠标移动的事件:
frame->Connect(wxEVT_MOTION,wxMouseEventHandler(MyFrame::OnMouseMove));
直接把事件ID与事件手柄联系起来。 参数function的问题大一些,就是这个显式强制类型转换的这个Handler,具体叫wx什么EventHandler呢?这个问题也好解决,因为官方文档里的 Classes By Category里的Event小节已经给出了形如wxFooEvent这样的事件类型的列表,只需要在相应的事件类型后面加上Handler就可以了。同样为了本文作为手册的完整性,将在本文后面给出全部Handler的列表。
最大的问题出在参数eventType上。形如wxEVT_MOTION、wxEVT_COMMAND_MENU_SELECTED这样的事件ID的名字,我们从何得知?这些奇形怪状的名字,纵然我们英语很强,也未必能造出和wxWidgets定义的一模一样的名字啊。比如写惯MFC的同好们很容易将鼠标移动事件ID写为wxMOUSEMOVE或wxMOUSE_MOVE,可这却是错的。最糟糕的是,文档中没有提供这些名字的列表!
有些同好可能发现了,对大部份事件类型的静态事件表的宏的说明中,包含了这方面的重要信息,例如wxPaintEvent里:
EVT_PAINT(func) Process a wxEVT_PAINT event.
左边是静态事件表需要的,右边是动态事件表需要的。左手静态,右手动态,好潇洒啊!然而,倘若你要处理窗口关闭事件(假设该事件的产生不是通过菜单选择,而是点窗口右上角的红叉叉),你跑到wxCloseEvent那里一看:
EVT_CLOSE(func) Process a close event, supplying the member function. This event applies to wxFrame and wxDialog classes.
你晕了……为什么文档编写者连这都不肯告诉你?!于是你尝试着用wxEVT_CLOSE,编译器告诉你不对。已经习惯了没事翻翻头文件的你就跑到
所幸这个情况并没有出现在大多数基本的事件里,但实际中总会需要处理那些不那么基本的事件的,每次都在这个细节上卡这么久的壳太不划算了。所以我把事件 ID列表从
。
星期二, 八月 04, 2009
wxWidgets-2.8.10 undefined reference to `wxXmlResource::LoadIconW(wxString const
在C++代码中调用XRC资源
wxXmlResource::Get()->LoadIcon(_T("appIco"));
链接的时候出现:
undefined reference to `wxXmlResource::LoadIconW(wxString const|
这个错误非常的奇怪,只是包含wx/xrc/xmlres.h,则出现这个错误
经过分析发现LoadIconW在wx/msw/winundef.h中有如下定义:
#ifdef LoadIcon
#undef LoadIcon
inline HICON LoadIcon(HINSTANCE hInstance, LPCTSTR lpIconName)
{
#ifdef _UNICODE
return LoadIconW(hInstance, lpIconName);
#else // ANSI
return LoadIconA(hInstance, lpIconName);
wxXmlResource::Get()->LoadIcon(_T("appIco"));
链接的时候出现:
undefined reference to `wxXmlResource::LoadIconW(wxString const|
这个错误非常的奇怪,只是包含wx/xrc/xmlres.h,则出现这个错误
经过分析发现LoadIconW在wx/msw/winundef.h中有如下定义:
#ifdef LoadIcon
#undef LoadIcon
inline HICON LoadIcon(HINSTANCE hInstance, LPCTSTR lpIconName)
{
#ifdef _UNICODE
return LoadIconW(hInstance, lpIconName);
#else // ANSI
return LoadIconA(hInstance, lpIconName);