用vala给go程序加上gui

作者: 从火星来 | 来源:发表于2018-11-02 10:11 被阅读33次

    vala语言编写gtk界面程序非常简单方便,而且它编译时会翻译成c语言,所以可以方便的调用go编译器生成的c-archive

    一、把 C 头文件翻译称vala可用的 vapi 文件

    要用vala调用go导出的函数,就先要把 C 头文件翻译称vala可用的 vapi 文件。例如我的一个go程序用go build -buildmode=c-archive生成了两个文件:libmychat.alibmychat.h,头文件提供的函数如下:

    extern GoInt GetMsg(char** p0, char** p1);
    
    extern void ChatInit(int p0);
    
    extern GoInt SetIRCServer(char* p0);
    
    extern GoInt SetNick(char* p0);
    
    extern GoInt SetRoom(char* p0, char** p1);
    
    extern GoInt SetKey(char* p0);
    
    extern char* GetHead(int p0);
    
    extern void Quit();
    
    extern void Say(char* p0, char* p1);
    
    extern GoInt GetStep();
    

    翻译成对应的mychat.vapi文件内容如下:

    [CCode (cheader_filename="libmychat.h")]
    
    public static int GetMsg(out string p0, out string p1);
    
    public static void ChatInit(int p0);
    
    public static int SetIRCServer(string p0);
    
    public static int SetNick(string p0);
    
    public static int SetRoom(string p0, out string p1);
    
    public static int SetKey(string p0);
    
    public static string GetHead(int p0);
    
    public static void Quit();
    
    public static void Say(string p0, string p1);
    
    public static int GetStep();
    

    对应关系非常简单吧。

    二、如何实现go程序回调vala程序的问题

    上面已经解决打了vala调用go程序导出的函数的问题,但是还不够,我们在处理外部消息的时候经常需要让go线程回调vala以便显示信息。要直接实现这个功能可能很复杂,但是转个弯,让go程序内部把信息发送到一个channel,导出一个专门读取和处理这个channel的阻塞型函数,而vala程序可以用一个独立线程循环调用这个函数,并处理接收到的信息。问题就这么简单的解决了。

    下面就是一个示例:

    //go 代码,使用 cgo 直接从参数返回2个 C 字符串
    //export GetMsg
    func GetMsg(from, msg **C.char) int {
        m, ok := <-chan1
        var ret int
        if ok {
            *from = C.CString(m.From)
            *msg = C.CString(m.Msg)
            ret = 1
        } else {
            *from = nil
            *msg = nil
            ret = 0
        }
        return ret
    }
    
    //vala 代码
    //循环读取消息的函数
    public int loop_msgs(){
            int ret;
            while(true){
                string from,msg;
                ret = GetMsg(out from, out msg);
                            //处理和显示
                            ......
            }
        }
    //在线程中调用 loop_msgs
    var thread = new Thread<int>.try ("irc1", this.loop_msgs);
    

    三、如何编译

    展示一个Makefile,大家就很容易理解了。

    mimichat:chatui.vala mychat.vapi
        valac -o mimichat --pkg gtk+-3.0 --thread -X -I. -X -L. -X -lmychat chatui.vala mychat.vapi
    

    结语 调用和回调问题都解决了,相信基本没有什么功能不能实现了吧。

    相关文章

      网友评论

        本文标题:用vala给go程序加上gui

        本文链接:https://www.haomeiwen.com/subject/evdqxqtx.html