将C联合转换为pascal变体记录

时间:2015-07-31 11:57:08

标签: c pascal records

帮助n00b!

我正在为C库编写绑定,我遇到了联合声明/变体记录。我试图让它工作,但没有运气。

原始C代码:

struct _PurpleConversation
{
    PurpleConversationType type;  
    PurpleAccount *account;       
    char *name;                 
    char *title;
    gboolean logging;
    GList *logs;                
    union
    {
        PurpleConvIm   *im;
        PurpleConvChat *chat;
        void *misc;
    } u;
    PurpleConversationUiOps *ui_ops;
    void *ui_data;
    GHashTable *data;
    PurpleConnectionFlags features;
    GList *message_history;
};

我的翻译:

TPurpleConversation = record
    convtype : TPurpleConversationType; 
    account: PPurpleAccount;
    name : PChar;
    title: PChar;
    logging: Boolean32;
    logs: PGlist;
    ui_ops: TPurpleConversationUiOps;
    ui_data : Pointer;
    data: PGHashTable;                      
    features : TPurpleMessageFlags;
    message_history : PGList;         

    case u : integer of
    0:(
        im: PPurpleConversationIm;          
        chat: PPurpleConversationChat; 
        misc: Pointer;
    );
end;

我认为它错了:

  • 首先出现的问题是varaiant记录位于不同的位置,但在Pascal中它只能放在记录的末尾。
  • 错误地声明变体记录。

我向#fpc频道询问了一些帮助,他们指出的两个可能的变种是制作两条记录(一条只有变量记录),第二条是使用这个case语句。最后一个选项应该是最兼容的。

我以前没有在Pascal中使用过这种语句的经验,所以有人可以解释一下这将如何工作?

谢谢!

2 个答案:

答案 0 :(得分:2)

第一个通常是通过将联合之后的字段移动到联合的一个分支来修复,就像下面的例子中一样,但是因为联合不是匿名的,所以不会在这里工作。

未经测试的快速重排:

TPurpleConversation = record
    convtype : TPurpleConversationType; 
    account: PPurpleAccount;
    name : PChar;
    title: PChar;
    logging: Boolean32;
    logs: PGlist;
    case u : integer of
    0:( im: PPurpleConversationIm;     );
    1: (chat: PPurpleConversationChat; );
    2: (   misc: Pointer;     
           ui_ops: TPurpleConversationUiOps;
           ui_data : Pointer;
           data: PGHashTable;                      
           features : TPurpleMessageFlags;
           message_history : PGList;         
    );
end;

可以从文档中学习语法:http://www.freepascal.org/docs-html/ref/refsu19.html

但这要求ui_ops使message_history以u。为前缀。

Gboolean应该在gtk / glib标题中声明,当然打包仍然会搞砸了。

答案 1 :(得分:0)

所以我使用了Marco van de Voort的代码并对其进行了一些修改 - 也许有人觉得这很有帮助。

{$packrecords C}
TPurpleConversation = record
    convtype : TPurpleConversationType; 
    account: PPurpleAccount;
    name : PChar;
    title: PChar;
    logging: GBoolean;
    logs: PGlist;

    case longint of
      0 : ( im : PPurpleConversationIm );
      1 : ( chat : PPurpleConversationChat );
      2 : ( misc : Pointer;
            ui_ops: TPurpleConversationUiOps;
            ui_data : Pointer;
            data: PGHashTable;                      
            features : TPurpleMessageFlags;
            message_history : PGList;         
        );
end;

做了什么:

  • 添加了字节对齐指令{$ packrecords C}。
  • 从变体记录中删除了标记。

这允许我继续使用该对象一个函数参数等,一切都很顺利。但是还有其他绑定问题不值得付出努力,所以我将FreePascal转移到这个项目并开始在C中推送它。

感谢您的帮助!