2008年6月5日星期四

Qt environment for Marvell board.

用于Marvell的板子。
=============== 安装toolchain 以及 Qt
1, create diretory /CMMB

2, cp PlatformRel_Linux2.6.21_MHLV.tgz into the /CMMB

3, tar xvzf PlatformRel_Linux2.6.21_MHLV.tgz
this step create dir pxalinux.

4, cd /CMMB/pxalinux/toolchain
tar xvzf arm-iwmmxt-linux-gnueabi-4.1.1-gpl-lgpl.tgz
This stup create toolchain files in dir /CMMB/pxalinux/toolchain/arm-linux-4.1.1

5, modify the /root/.bashrc to add the path /CMMB/pxalinux/toolchain/arm-linux-4.1.1/bin
into the env var PATH.
export PATH=/CMMB/pxalinux/toolchain/arm-linux-4.1.1/bin:$PATH

6, cd /CMMB/pxalinux/package/usage-model-7.0.5
tar xvzf qtopia-src-gpl.tgz
After this step, the dir qtopia_2.2.0 is created.

7, cd /CMMB/pxalinux/package/usage-model-7.0.5/qtopia_2.2.0
and run the shell: yes | ./build_qtopia.sh > build.log

8,
// 设定 qmake路径。
export PATH=/CMMB/pxalinux/package/usage-model-7.0.5/qtopia_2.2.0/work/qtopia-free-2.2.0/dqt/bin:$PATH
export QMAKESPEC=/CMMB/pxalinux/package/usage-model-7.0.5/qtopia_2.2.0/work/qtopia-free-2.2.0/qtopia/mkspecs/qws/linux-arm-g++

cd /CMMB/pxalinux/package/usage-model-7.0.5/qtopia_2.2.0/work/qtopia-free-2.2.0
chmod +x setQpeEnv
./setQpeEnv


=============== 配置Qt开发环境

1, Create account for development
groupadd cmmbdev
adduser cmmb -g cmmbdev
passwd cmmb

2, Create a shell setDevEnv.sh, including:
# 导入Qtopia环境变量
source /CMMB/pxalinux/package/usage-model-7.0.5/qtopia_2.2.0/work/qtopia-free-2.2.0/setQpeEnv

# 设置toolchain路径
export PATH=/CMMB/pxalinux/toolchain/arm-linux-4.1.1/bin:$PATH

# 设置qmake路径
export PATH=/CMMB/pxalinux/package/usage-model-7.0.5/qtopia_2.2.0/work/qtopia-free-2.2.0/dqt/bin:$PATH

# 设置qmake环境变量配置路径
export QMAKESPEC=/CMMB/pxalinux/package/usage-model-7.0.5/qtopia_2.2.0/work/qtopia-free-2.2.0/qtopia/mkspecs/qws/linux-arm-g++


3, add . ./setDevEnv.sh into the cmmb user's .bashrc

4, chmod -R +r /CMMB/pxalinux
cd /CMMB
mkdir tvp
chown -R cmmb tvp

5, qmake -project
modify tvp.pro to include:
QMAKE_LIBS_QT += -ljpeg -luuid -lts -lqpe

6, qmake
7, make



通用的QT安装
1) 升级Kernel
rpm -ql | grep kern
yum intall kern*
2) 修改grub.conf使console支持FrameBuffer。在引导界面可以看到小企鹅。/dev目录下有设备fb0。 这样从console中就可以直接运行GUI程序了。



试图生成 libqte-mt.so, 用于QThread.
2) qt2
./configure -qt2 '-no-xft -thread -I/usr/include -I/usr/include/freetype2 -I/usr/include/freetype'
ln -sf /pub/qtopia-free-2.2.0/dqt/lib/libqt-mt.so.3.3.5 /pub/qtopia-free-2.2.0/qtopia/lib/libqte-mt.so

3)
./configure -qt2 '-no-xft -thread -I/usr/include -I/usr/include/freetype2 -I/usr/include/freetype'

以上步骤都不能生成libqte-mt.so
通过修改config.cache,可以生成libqte-mt.so了。
QPEDIR=/pub/qtopia-free-2.2.0/qtopia
QTOPIA_DEPOT_PATH=/pub/qtopia-free-2.2.0/qtopia
TMAKEDIR=/pub/qtopia-free-2.2.0/tmake
DQTDIR=/pub/qtopia-free-2.2.0/dqt
QT2DIR=/pub/qtopia-free-2.2.0/qt2
QTEDIR=/pub/qtopia-free-2.2.0/qt2
QPE_CFG="-edition pda -displaysize 240x320 -no-qtopiadesktop -release -platform 'linux-g++' -xplatform 'linux-generic-g++'"
QTE_CFG="-embedded -no-xft -qconfig qpe -qvfb -thread -depths 4,8,16,32 -system-jpeg -gif -D QT_TRANSFORM_VFB -release -platform 'linux-g++' -xplatform 'linux-generic-g++'"
QT2_CFG="-no-opengl -no-xft -no-sm -platform 'linux-g++'"
DQT_CFG="-thread -qt-gif -fast -platform 'linux-g++'"
USE_CACHE="no"
这样,Qt2的线程包没有生成,估计要设置-thread 到QT2_CFG中.

虽然这样做生成了libqte-mt.so, 但是把QThread用于QTopia程序(带GUI)时仍旧发生段错误. 普通的QT程序使用QThread时就没有问题.

后来通过配置qtopia的编译发现了这段警告. 看来在qtopia2.2下使用QThread是不稳定的.
[root@localhost qtopia]# ./configure -debug -thread -I/usr/include:/usr/include/freetype:/usr/include/freetype2 -qvfb -qtopia
QPEDIR = /pub/qtopia-free-2.2.0/qtopia
DEPOT = /pub/qpe2.2/qtopia
The following configuration values have been guessed or autodetected:
-arch generic
-displaysize 240-320
-edition pda
-fontfamilies helvetica fixed micro smallsmooth smoothtimes
-fontsizes all
-fontstyles 50 50i 75 75i
-languages en_US
-platform linux-g++
-xplatform linux-generic-g++

WARNING: Trolltech does not support building Qtopia against a multi-threaded Qt.
While it should work, Trolltech can make no guarantees about the ability
of Qtopia to operate correctly when Qt is multi-threaded. If you wish to
use threads in your own apps, you should consider using pthreads directly.

Symlinking header files to include directory
Creating qmake.......



因为以上Qtopia2.2中QThread的问题,这两天改用qtopia-opensource-4.3.1了. 感觉不错。
Qtopia-opensource-4.3.1的安装。
1)安装。
./configure 过程中有警告和错误提示如下。但是不用管它们,依旧可以编译通过。
Project ERROR: This is a dummy profile to be used for translations ONLY.
WARNING: Failure to find: qvfbhdr.h
在gmake的过程中,提示缺少库libXtst, libXmu,而不能继续。此时需要使用 yum install libXtst*, yum install libXmu*进行安装。

2)gmake install。
这一步会生成image。所有要运行的程序都要放在image/bin目录下。这是完整的Qtopia运行环境。

3)样例程序。
把example的样例程序随便copy到某个目录里。通过qtopiamake生成Makefile. 用make install INSTALL_ROOT="imagePath" 进行编译安装。



gstreamer 库与Qtopia的结合。
把利用gstreamer播放mp3的函数封装到动态库libmyGstLib.so中。Qtopia的GUI程序直接库中的函数。遇到的问题及解决如下:
1)段错误。
写了一个很简单的动态库供qtopia程序适用,一切正常。 排除了qtopia的问题。
int startPlayer (int argc, char *argv[]); 方法中有: gst_init (&argc, &argv); 而在Qtopia对其的调用中传递的是startPlayer(1, NULL);
怀疑gstreamer使用了argc, argv参数。于是就把NULL改为了一个字符串数组。问题解决了。但是又说没有找到"mad"插件。

又写了一个只有main函数,调用动态库的程序,却没有mad插件的错误。播放mp3没有问题。
察看了一下编译main函数使用的gcc参数。
libtool --mode=link gcc `pkg-config --cflags --libs gstreamer-0.10` -o gstTestApp test.c
gcc -pthread -I/usr/local/include/gstreamer-0.10 -I/usr/include/glib-2.0 -I/usr/lib/glib-2.0/include -I/usr/include/libxml2 -pthread -o myprog test.c -L/usr/local/lib -L/lib /usr/local/lib/libgstreamer-0.10.so -lrt -lgobject-2.0 -lgmodule-2.0 -ldl -lgthread-2.0 -lxml2 -lz -lm -lglib-2.0 -Wl,--rpath -Wl,/usr/local/lib -Wl,--rpath -Wl,/usr/local/lib

而libmad安装后也提示:
If you ever happen to want to link against installed libraries
in a given directory, LIBDIR, you must either use libtool, and
specify the full pathname of the library, or use the `-LLIBDIR'
flag during linking and do at least one of the following:
- add LIBDIR to the `LD_LIBRARY_PATH' environment variable
during execution
- add LIBDIR to the `LD_RUN_PATH' environment variable
during linking
- use the `-Wl,--rpath -Wl,LIBDIR' linker flag
- have your system administrator add LIBDIR to `/etc/ld.so.conf'

See any operating system documentation about shared libraries for
more information, such as the ld(1) and ld.so(8) manual pages.
通过把这些库和编译选项加入到了myGstLib的编译文件中后,程序就可以播放mp3了.

2) Qt中的Singal-slot机制是同步的.如果某个signal没有处理完毕,界面就会冻结。所以需要使用线程进行播放。




2008年4月24日星期四

VS2008创建wxwidget 项目

尝试用vs2008 express版学习wxwidget。建立了一个helloworld都没能链接成功。照网上的文章做了也不行。最后还是参照其自带的samples把项目属性设置成功了。至于以前设置的错误,希望随着时间的积累能够原因。步骤大致如下:
1,把wxWidget安装到 D:\wxWidgets-2.8.7。设置环境变量WXWIN=D:\wxWidgets-2.8.7。
2,用vs2008打开D:\wxWidgets-2.8.7\build\msw\wx.dsw,编译所有代码。
3,可以另起一个solution,创建一个空项目。
4,把helloworld程序past进去。
5,设置项目属性:
additional include directories: "$(WXWIN)\lib\vc_lib\mswd";"$(WXWIN)\include"
preprocessor: WIN32;_DEBUG;__WXMSW__;__WXDEBUG__;_WINDOWS;NOPCH
additional library directories: $(WXWIN)\lib\vc_lib

错误的版本加入了一些其它头文件路径。

2008年4月18日星期五

对google BLOG HTML代码的修改。

1)使用默认的模版代码,不能在IE下浏览。据说是因为编码的问题。把<$BlogMetaData$>放到head标签后面。


2)现在都是宽屏的显示器了。模版中的正文宽度太狭窄了,调宽:
把所有width:700px的地方都换成900px, 因为模版中content图片的宽度是固定的 900所以去调下面粗体部分。
#main-content {
width:900px;
background:#FFF3DB url("http://www.blogblog.com/scribe/bg_paper_mid.jpg") repeat-y;
margin:0;
text-align:left;
display:block;
}

@media all {
#main {
width:630px; // 由原来的430改为630。
float:right;
padding:8px 0;
margin:0;
}
这样整个content布局宽度增加了200pix。

理解libjingle的ThreadManager

Thread Local Storage(TLS)的作用。
进程中的所有线程共享进程的虚拟地址空间。方法中的局部变量对于每个运行这个方法的线程是独立唯一的。但是,全局的静态变量是被这个进程中的所有线程共享的。通过使用TLS你可以为每个线程提供独立的数据。

一般在process初始化时分配tls Index。这样随后这个process中的线程就可以通过这个index存储与每个线程自己相关的数据了。
msdn关于TlsAlloc()的说明:
Allocates a thread local storage (TLS) index. Any thread of the process can subsequently use this index to store and retrieve values that are local to the thread, because each thread receives its own slot for the index.
If the function succeeds, the return value is a TLS index. The slots for the index are initialized to zero.
The threads of the process can use the TLS index in subsequent calls to the TlsFree, TlsSetValue, or TlsGetValue functions. The value of the TLS index should be treated as an opaque value; do not assume that it is an index into a zero-based array
TLS indexes are typically allocated during process or dynamic-link library (DLL) initialization. After a TLS index has been allocated, each thread of the process can use it to access its own TLS storage slot. To store a value in its TLS slot, a thread specifies the index in a call to TlsSetValue. The thread specifies the same index in a subsequent call to TlsGetValue, to retrieve the stored value.
TLS indexes are not valid across process boundaries. A DLL cannot assume that an index assigned in one process is valid in another process.


libjingel中的ThreadManager。
这个类完成对所有Thread实例线程的管理。其中就分配了一个slot index用于保存current thread。

ThreadManager使用ScriticalSecion,ScriticalSection相当于java中的synchronize中使用的锁。
windows使用CRITICAL_SECTION 定义锁。POSIX使用pthread_mutex_t。
相应的方法分别是:
windows: InitializeCriticalSection(&crit_)、EnterCriticalSection(&crit_)、 LeaveCriticalSection(&crit_)、DeleteCriticalSection(&crit_)。
POSIX: pthread_mutex_init()、pthread_mutex_lock(&mutex_)、 pthread_mutex_destroy(&mutex_)、 pthread_mutex_unlock(&mutex_)
ScriticalScope则相当于java中的synchronize块。

CreateThread
Widows 下创建线程的签名。 HANDLE CreateThread( LPSECURITY_ATTRIBUTES lpsa, DWORD cbStack, LPTHREAD_START_ROUTINE lpStartAddr, LPVOID lpvThreadParam, DWORD fdwCreate, LPDWORD lpIDThread);
lpStartAddr是线程运行起始地址,函数指针。lpvThreadParam为函数的参数。
thread_ = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)PreRun, this, flags, NULL);
void *Thread::PreRun(void *pv) {
Thread *thread = (Thread *)pv;
ThreadManager::SetCurrent(thread); // 此处把thread放到了TLS中了。
thread->Run();
return NULL;
}


[都怀疑java的native code是不是都是用了ACE的东西了,至少思路该是一样的吧。]

2008年4月13日星期日

sigslot in libjingle

The libjingle depends on the sigslot very much. From the Pattern's view, the signal-slot follows the Observer pattern.
To use the sigslot, there are 3 steps.
1) Define a Sender. The sender has a signal.
2) Of course, there's a Receiver which extends from the sigslot::slot. The receiver is the slot.
3) Somewhere, there must be a method that will connect the Sender's signal to the Receiver's slot(s) by calling the signal's connect method.
SignalA maybe is defined like this: sigslot::signal2 SignalA;
aReceiver is an object whose class inherits from sigslot::has_slots<>
aFunctionPointer is the processor of a signal. In this case, this processor method need two parameters.
Connect the signalA with the receiver's function just like this:
SignalA.connect(aReceiver , aFunctionPointer);

Reviewed these C++ keywords/concept today.
extern explicit "const member function"