关于代码风格和宏

这是个反思的时机。

由于现在fcitx只有我一个人修改,不需要合作的时候怎么写都无所谓。主要是让一位兄弟望而却步。

我的代码风格到底猎奇吗?

他对于libfcitx-config这个库的意见最大

fcitx的代码现在总体上受了很多其他的代码影响,比如插件的设计,灵感来源于compiz,包括配置文件的设计,比如采用独立文件描述配置文件,这样fcitx-config-gtk就可以像ccsm一样简单设计了。同时为了易于手动修改,于是采用了类ini的写法。

然后为了在代码中方便取用配置文件的值,可以将配置文件的值和一个c的struct绑定,为了方便描述这种绑定这里使用了大量的宏。

使用宏的习惯是我从Postgresql继承来的,学校的开发涉及Postgresql,里面也使用了很多宏,比如系统表的初始值,系统表的定义。

CONFIG_BINDING_BEGIN(FcitxPinyinConfig);
CONFIG_BINDING_REGISTER("Pinyin", "PinyinPriority", iPinyinPriority);
CONFIG_BINDING_REGISTER("Pinyin", "ShuangpinPriority", iShuangpinPriority);
CONFIG_BINDING_REGISTER("Pinyin", "DefaultShuangpinSchema", strDefaultSP);
CONFIG_BINDING_REGISTER("Pinyin", "UseCompletePinyin", bFullPY);
CONFIG_BINDING_REGISTER("Pinyin", "AutoCreatePhrase", bPYCreateAuto);
CONFIG_BINDING_REGISTER("Pinyin", "SaveAutoPhrase", bPYSaveAutoAsPhrase);
CONFIG_BINDING_REGISTER("Pinyin", "AddFreqWordKey", hkPYAddFreq);
CONFIG_BINDING_REGISTER("Pinyin", "DeleteFreqWordKey", hkPYDelFreq);
CONFIG_BINDING_REGISTER("Pinyin", "DeleteUserPhraseKey", hkPYDelUserPhr);
CONFIG_BINDING_REGISTER_WITH_FILTER("Pinyin", "InputWordFromPhraseKey", strPYGetWordFromPhrase, FilterGetWordFromPhrase);
CONFIG_BINDING_REGISTER("Pinyin", "BaseOrder", baseOrder);
CONFIG_BINDING_REGISTER("Pinyin", "PhraseOrder", phraseOrder);
CONFIG_BINDING_REGISTER("Pinyin", "FreqOrder", freqOrder);
CONFIG_BINDING_REGISTER_WITH_FILTER("Pinyin", "FuzzyAnAng", MHPY_C[0].bMode, FilterAnAng);
CONFIG_BINDING_REGISTER("Pinyin", "FuzzyEnEng", MHPY_C[1].bMode);
CONFIG_BINDING_REGISTER("Pinyin", "FuzzyIanIang", MHPY_C[2].bMode);
CONFIG_BINDING_REGISTER("Pinyin", "FuzzyInIng", MHPY_C[3].bMode);
CONFIG_BINDING_REGISTER("Pinyin", "FuzzyOuU", MHPY_C[4].bMode);
CONFIG_BINDING_REGISTER("Pinyin", "FuzzyUanUang", MHPY_C[5].bMode);
CONFIG_BINDING_REGISTER("Pinyin", "FuzzyCCh", MHPY_S[0].bMode);
CONFIG_BINDING_REGISTER("Pinyin", "FuzzyFH", MHPY_S[1].bMode);
CONFIG_BINDING_REGISTER("Pinyin", "FuzzyLN", MHPY_S[2].bMode);
CONFIG_BINDING_REGISTER("Pinyin", "FuzzySSH", MHPY_S[3].bMode);
CONFIG_BINDING_REGISTER("Pinyin", "FuzzyZZH", MHPY_S[4].bMode);
CONFIG_BINDING_REGISTER("Pinyin", "Misstype", bMisstype);
CONFIG_BINDING_END()

比如这段代码。

宏的目的是为了使得机械重复的代码变得精简已读。那么这里如何呢?我觉得除了分号的使用(最后应该统一不用分号最好……),明显把这部分变得更加易读了(个人观点)。如果宏加上合适的文档说明,应该可以明确表达出这段代码的含义。

再谈到关于模块之间的互相调用。这部分的思想同样来源于Postgresql。以及之前看到的关于ABI的文章。

每个模块有自己的名称(固定不变),每个模块注册对应的函数,每个函数有自己的ID(固定不变),每个函数有固定的参数。真实参数通过这个固定参数的一个结构体传递,全部传递指针。

#define FCITX_X11_NAME "fcitx-x11"
#define FCITX_X11_GETDISPLAY 0
#define FCITX_X11_GETDISPLAY_RETURNTYPE Display*
#define FCITX_X11_ADDXEVENTHANDLER 1
#define FCITX_X11_ADDXEVENTHANDLER_RETURNTYPE void
#define FCITX_X11_REMOVEXEVENTHANDLER 2
#define FCITX_X11_REMOVEXEVENTHANDLER_RETURNTYPE void
#define FCITX_X11_FINDARGBVISUAL 3
#define FCITX_X11_FINDARGBVISUAL_RETURNTYPE Visual*
#define FCITX_X11_INITWINDOWATTR 4
#define FCITX_X11_INITWINDOWATTR_RETURNTYPE void
#define FCITX_X11_SETWINDOWPROP 5
#define FCITX_X11_SETWINDOWPROP_RETURNTYPE void
#define FCITX_X11_GETSCREENSIZE 6
#define FCITX_X11_GETSCREENSIZE_RETURNTYPE void
#define FCITX_X11_MOUSECLICK 7
#define FCITX_X11_MOUSECLICK_RETURNTYPE void

// 实际函数示例
static void* X11GetDisplay(void* x11priv, FcitxModuleFunctionArg arg);

这里注册的是X11的模块名称以及相关函数。宏名称的定义的格式是约定好的。

typedef struct FcitxModuleFunctionArg
{
    void* args[10];
} FcitxModuleFunctionArg;

void* InvokeModuleFunctionWithName(struct FcitxInstance* instance, const char* name, int functionId, FcitxModuleFunctionArg args);

#define InvokeFunction(INST, MODULE, FUNC, ARG)  \
    ((MODULE##_##FUNC##_RETURNTYPE) InvokeModuleFunctionWithName(INST, MODULE##_NAME, MODULE##_##FUNC, ARG))


实际调用的时候使用InvokeFunction这个宏。这样实际调用的时候就是这样子。可以明显看出是调用FCITX_X11的GETDISPLAY函数。

dpy = InvokeFunction(instance, FCITX_X11, GETDISPLAY, arg);

关于以上写法,诸君,你们以为呢。(实际毫无反省之意……)

This entry was posted in fcitx development. Bookmark the permalink.

12 Responses to 关于代码风格和宏

  1. pipitu says:
    Firefox 5.0 GNU/Linux

    宏有什么错!

  2. shellex says:
    Google Chrome 13.0.782.15 GNU/Linux x64

    我觉得挺好啊。

  3. shellex says:
    Google Chrome 13.0.782.15 GNU/Linux x64

    @shellex 是宏爱好者

  4. 右京样一 says:
    Google Chrome 12.0.742.112 GNU/Linux

    预编译那地方有好多好长的名字啊……意思是在函数里传进一个数字实现一个功能吗?

  5. 沈觅仁 says:
    Opera 11.11 GNU/Linux

    如果是多人合作写的代码,这么长的宏名字肯定会被再次defne的。。。总会有我这样的简约派出现。。

    PS,成功抓了本页面与ikde.org的页面内容。表示很高兴

  6. csslayer says:
    Firefox 5.0 GNU/Linux x64

    @沈觅仁 ……这不太好吧。。。。= =b
    @右京样一 Yes

  7. 右京样一 says:
    Google Chrome 12.0.742.112 Windows 7

    @沈觅仁 我倒不反感名字本身有多长,不过最痛苦的是如果反复使用一个函数的话会很痛苦,需要一遍一遍地码自己已经码过N遍的字,复制粘贴的话比码字更慢,这就太郁闷了……

  8. csslayer says:
    Firefox 5.0 GNU/Linux x64

    @右京样一 那是你的ide太烂……
    我用kdevelop不管多长,基本四个字母就确定范围了……

  9. 右京样一 says:
    Google Chrome 12.0.742.112 GNU/Linux

    @csslayer 我没IDE……当时是用Vim……

  10. siqiguo says:
    Google Chrome 12.0.742.112 Windows 7

    受pg荼毒很深啊

  11. csslayer says:
    Firefox 5.0 GNU/Linux x64

    @siqiguo 确实确实……

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.