星期四, 八月 20, 2009

SQLITE 3支持多线程并发访问。

需要在编译成dll或.o的时候,加入编译选项-DSQLITE_THREADSAFE=2

gcc -c sqlite3.c -o sqlite3.dll -DSQLITE_THREADSAFE=2

http://sqlite.org/threadsafe.html

星期三, 八月 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
  1. class Port
  2. {
  3. private:
  4. char *brand;
  5. char style[20]; // i.e. tawny, ruby, vintage
  6. int bottles;
  7. public:
  8. Port(const char *br = "none", const char *st = "none", int b = 0);
  9. Port(const Port &p); // copy constructor
  10. virtual ~Port() { delete [] brand;}
  11. Port & operator=(const Port &p);
  12. Port & operator+=(int b);
  13. Port & operator-=(int b);
  14. int BottleCount() const {return bottles;}
  15. virtual void Show() const;
  16. friend ostream &operator<<(ostream &os, const Port &p);
  17. };
  18. class VintagePort : public Port
  19. {
  20. private:
  21. char * nickname; // i.e. The Noble, or Old Velvet, etc.
  22. int year; // vintage year
  23. public:
  24. VintagePort();
  25. VintagePort(const char *br, int b, const char *nn, int y);
  26. VintagePort(const VintagePort &vp);
  27. ~VintagePort() {delete [] nickname;}
  28. void Show() const;
  29. friend ostream & operator<<(ostream &os, const VintagePort & vp);
  30. };

星期六, 八月 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

星期三, 八月 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,编译器告诉你不对。已经习惯了没事翻翻头文件的你就跑到里去找了,一搜索就出来了。原来是wxEVT_CLOSE_WINDOW,这可真是情理之中意料之外啊,反正我当时是接近吐血了……
所幸这个情况并没有出现在大多数基本的事件里,但实际中总会需要处理那些不那么基本的事件的,每次都在这个细节上卡这么久的壳太不划算了。所以我把事件 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);