几则技巧 这几天帮同事解决了几个问题,写在这里作为备忘,其他朋友也可以参考。 l 建立 UNICODE 的 MFC 工程 (VC6) 。 按正常步骤建立一个 MFC 应用程序工程。 打开 : Project-Settings-C/C++ 。在 Preprocessor definitions 中定义 UNICODE 和 _UNICODE 两
几则技巧
这几天帮同事解决了几个问题,写在这里作为备忘,其他朋友也可以参考。
l 建立 UNICODE 的 MFC 工程 (VC6) 。
按正常步骤建立一个 MFC 应用程序工程。
打开 : Project->Settings…->C/C++ 。在 Preprocessor definitions 中定义 UNICODE 和 _UNICODE 两个宏。
打开 : Project->Settings…->Link 。选择 Output 类别,修改 Entry-Point Symbol 的值为 wWinMainCRTStartup 。
编译应该没有问题了。运行时若出现找不到 mfcxxx.dll ,从 VC 的安装文件中拷贝到系统目录就行了。
l DLL 内存释放问题 (VC6) 。
在 Windows 下,如果在一个 DLL 里分配的内存,在另外一个 DLL 或者在 EXE 里释放,程序可能会 crash 。这时多半是因为这些 DLL 和 EXE 链接了不同的运行库,不同运行库的堆是不同的,在一个堆里分配的内存,在另外一个堆里释放,就会 crash 。解决方案有两个:
方案一:打开 : Project->Settings…->C/C++ 。选择 Code Generation 类别,确保所有工程的 Use run-time library 的值是一致。
方案二:哪里分配就在哪里释放。 DLL 提供了分配函数,同时提供一个释放函数,这样可以确保在同一个堆里释放。
l 抽象工厂模式的一个实例。
同事在开发手机的 PC 模拟环境时,遇到这样一个问题:其可能通过串口与另外一个真实的手机通信,也可能通过 Socket 与另外一个模拟手机通信。由配置文件决定实际的通信方式。
首先自然会想到,建立一个抽象基类 Stream ,一个继承 Stream 的子类 SerialPortStream ,实现串口通信,和一个继承 Stream 的子类 SocketStream ,实现 Socket 通信。调用者通过抽象基类 Stream 的指针去调用不同子类的实现,从而避免大量 if/else 语句。
但是有好几地方都要创建这些对象,由于创建时仍然要关心具体的子类,前面的方法仍然不够完美。为了避免这些创建代码分散在不同的地方,可以采用抽象工厂模式。程序运行时,根据配置文件创建一个工厂对象,后面通过抽象工厂的指针去创建不同的子类。这样,调用者与实现者之间的耦合降到了最低。
l DBUS marshal 函数的参数个数。
DBUS 的 glib 封装的 marshal 函数,与 glib 原生的 marshal 完全一样。比如:
void
g_cclosure_marshal_VOID__INT (GClosure *closure,
GValue *return_value,
guint n_param_values,
const GValue *param_values,
gpointer invocation_hint,
gpointer marshal_data)
{
typedef void (*GMarshalFunc_VOID__INT) (gpointer data1,
gint arg_1,
gpointer data2);
register GMarshalFunc_VOID__INT callback;
register GCClosure * cc = (GCClosure*) closure;
register gpointer data1, data2;
g_return_if_fail (n_param_values == 2);
if (G_CCLOSURE_SWAP_DATA (closure))
{
data1 = closure-> data ;
data2 = g_value_peek_pointer (param_values + 0);
}
else
{
data1 = g_value_peek_pointer (param_values + 0);
data2 = closure-> data ;
}
callback = (GMarshalFunc_VOID__INT) (marshal_data ? marshal_data : cc ->callback);
callback (data1,
g_marshal_value_peek_int (param_values + 1),
data2);
}
语句 g_return_if_fail (n_param_values == 2); 有些让人迷惑,明明只有一个参数,为什么参数个数是 2 个。从这个函数的实现可以看出,第一个参数始终是对象本身,虽然 signal 只有一个参数,加上对象指针本身,参数个数变成 2 个了。
l 安装 FC5 的内核源码。
[root@localhost ~]# rpm -ivh kernel-2.6.15-1.2054_FC5.src.rpm
[root@localhost ~]# cd /usr/src/redhat/SPECS
[root@localhost SPECS]# rpmbuild -bp --target=i686 kernel-2.6.spec
[root@localhost SPECS]# cd BUILD/kernel-2.6.15/linux-2.6.15.i686/
[root@localhost linux-2.6.15.i686]# make menuconfig
[root@localhost linux-2.6.15.i686]#make
[root@localhost linux-2.6.15.i686]# rm /lib/modules/2.6.15-1.2054_FC5/build
[root@localhost linux-2.6.15.i686]# ln /lib/modules/2.6.15-1.2054_FC5/build /usr/src/redhat/BUILD/kernel-2.6.15/linux-2.6.15.i686/ -s