顯示具有 Vala 標籤的文章。 顯示所有文章
顯示具有 Vala 標籤的文章。 顯示所有文章

2012年10月21日 星期日

betaradio v1.5 released

BetaRadio 是一款使用 Vala 程式語言寫出來的網路收音機程式,專門用來收聽台灣的網路電台。

專案網址:
http://code.google.com/p/betaradio/

新功能:
1. 保持單一程式實體

錯誤修正:
1. 修正無法在 gnome session 底下使用
2. 修正記憶體洩漏
3. 修正 GTK+ thread 使用

原始碼下載:
http://code.google.com/p/betaradio/downloads/detail?name=betaradio-1.5.tar.bz2

2012年1月16日 星期一

Genie 程式語言

Genie 程式語言是 GNOME 計畫下的一個新的程式語言,跟 Vala 一起開發的,語法類似 Python,跟 Vala 一樣都是借助 GObject 來實現物件導向程式設計,也跟 Vala 一樣都是產生出 C 的程式碼,而且也因為 GObject 的關係可以輕易地產生其它程式語言的 binding。
例如:輸入以下的程式碼儲存成 hello.gs
init
        print "Hello World"
然後再執行以下的指令就可以看到結果了。
$ valac hello.gs
$ ./hello
如果說要看到中間轉譯出來的 C 語言程式碼可以輸入以下指令:
$ valac -C hello.gs
於是就可以看到 hello.c 產生出來了。
/* hello.c generated by valac 0.14.0, the Vala compiler
 * generated from hello.gs, do not modify */

#include <glib.h>
#include <glib-object.h>
#include <stdlib.h>
#include <string.h>

void _vala_main (gchar** args, int args_length1);

void _vala_main (gchar** args, int args_length1) {
        g_print ("Hello World\n");
}

int main (int argc, char ** argv) {
        g_type_init ();
        _vala_main (argv, argc);
        return 0;
}
看看裡面的內容是不是一般所熟悉的 C 語言程式碼。:)
參考資料:Genie - GNOME Live!

2011年8月31日 星期三

Project Euler - Problem 12

昨天在 TOSSUG 聚會上 Choupi 提到這個問題 Project Euler - Problem 12 於是就寫了以下的 Vala 程式碼來解這個問題
void main()
{
    int i = 0, number = 0;
    // 用來儲存質數分解的結果
    HashTable<string, int*> factors = null;

    do {
        // 逐個取出三角數
        number = triangle_number(++i);
        // 算出所有因數的個數直到比 500 還要大為止
    } while (factor_number_of(number, out factors) < 500);

    // 把算出來的答案印出來
    stdout.printf("Answer: %d\n", number);

    // 將答案驗算一遍
    print_factors(factors);
}

void print_factors(HashTable<string, int*> factors)
{
    int number = 1;

    List<unowned string> keys = factors.get_keys();
    // 把質因數表的鍵值依照數值大小重新排序
    keys.sort( (a, b) => {
        int num1 = int.parse(a);
        int num2 = int.parse(b);
        if (num1 < num2 ) {
            return -1;
        }
        else if (num1 > num2) {
            return 1;
        }
        else {
            return 0;
        }
    });

    // 驗算過程
    foreach (unowned string key in keys) {
        int* count = (int*) factors.lookup(key);
        int prime = int.parse(key);
        if (*count > 1) {
            stdout.printf("%d^%d*", prime, *count);
        }
        else {
            stdout.printf("%d*", prime);
        }
        // 重覆乘上質因數出現的次數
        for (int i = 0; i < *count; i++) {
            number = number * prime;
        }
        free(count);
    }

    stdout.printf("\b=%d\n", number);
}

// 三角數的計算
int triangle_number(int num)
{
    return num * (num + 1) / 2;
}

// 找出某數值的質因數分解
int factor_number_of(int number, out HashTable<string, int*> table)
{
    table = new HashTable<string, int*>(str_hash, str_equal);
    do {
        // 找出該數值的平方根
        int root = sqrt_floor_of(number);
        int previous = number;

        // 從小到大用質因數去整除直到超過平方根
        for (int i = 0; prime_number_of(i) <= root; i++) {
            int prime = prime_number_of(i);
            if (number % prime == 0) {
                // 遞增質因數表的數值
                int* count = (int*) table.lookup(prime.to_string()) ?? malloc0(sizeof(int));
                *count = *count + 1;
                table.replace(prime.to_string(), count);
                number = number / prime;
                break;
            }
        }

        // 如果 number 沒有變動過,number 就是質數。
        if (number == previous) {
            // 遞增質因數表的數值
            int* count = (int*) table.lookup(number.to_string()) ?? malloc0(sizeof(int));
            *count = *count + 1;
            table.replace(number.to_string(), count);
            break;
        }
    } while (number != 1);

    int result = 1;

    // 計算所有因數的個數
    foreach (int* count in table.get_values()) {
        result = result * (*count + 1);
    }

    return result;
}

// 計算平方根
int sqrt_floor_of(int num)
{
    return (int) Math.sqrt((double) num);
}

// 準備一個用來 cache 計算過的質數表
static List<int> prime_table = new List<int>();

// 質數計算
int prime_number_of(uint index)
{
    if (index < prime_table.length()) {
        // 直接從 cache 中取出
        return prime_table.nth_data(index);
    }

    // 第一個質數為 2
    if (index == 0) {
        prime_table.append(2);
        return 2;
    }
    // 第二個質數為 3
    else if (index == 1) {
        prime_table.append(3);
        return 3;
    }
    // 第三個後的質數計算
    else {
        int candidate = prime_table.nth_data(prime_table.length() - 1) + 2;
        do {
            bool is_prime = true;
            foreach (int number in prime_table) {
                if (candidate % number == 0) {
                    is_prime = false;
                    break;
                }
            }
            if (is_prime) {
                prime_table.append(candidate);
                return candidate;
            }
            candidate = candidate + 2;
        } while (true);
    }
}
將以上程式碼儲存成 p12.vala 或是直接從 gist: 1182715 下載 然後編譯執行
$ valac p12.vala -X -lm && ./p12
Answer: 76576500
2^2*3^2*5^3*7*11*13*17=76576500

2011年1月5日 星期三

BetaRadio v1.2 釋出

功能跟 v1.1 一樣沒有改變,不過程式碼完全使用 Vala 重寫一遍。
原始碼下載:http://betaradio.googlecode.com/files/betaradio-1.2.tar.bz2
編譯方法請參考 http://code.google.com/p/betaradio/wiki/InstallationFromSourceCode

PPA for Ubuntu 9.10/10.04/10.10
$ sudo add-apt-repository ppa:fourdollars/betaradio
$ sudo apt-get update
$ sudo apt-get install betaradio

2010年10月9日 星期六

使用 GNU Build System 管理用 Vala 寫的 GTK+ 程式

延續先前的文章『使用 GNU Build System (aka Autotools) 來管理 Vala 編譯流程

首先準備好 GTK+ 的 Vala 原始碼檔案 MyApp.vala
using Gtk;

namespace ValaTutorial
{
    class MyApp : Gtk.Window
    {
        public MyApp ()
        {
            var button = new Button.with_label ("Click me!");
            add (button);

            button.clicked.connect (on_clicked);
        }

        private void on_clicked (Gtk.Button button)
        {
            stdout.printf ("Ouch!\n");
        }

        public static int main (string[] args)
        {                                                    
            Gtk.init (ref args);

            var app = new MyApp ();
            app.show_all ();

            app.destroy.connect (Gtk.main_quit);

            Gtk.main ();
            return 0;
        }
    }
}
然後再準備一個 Makefile.am
# AM_VALAFLAGS = --pkg gtk+-2.0            

bin_PROGRAMS = MyApp

MyApp_SOURCES = MyApp.vala
MyApp_CPPFLAGS = @GTK_CFLAGS@
MyApp_LDFLAGS = @GTK_LIBS@
MyApp_VALAFLAGS = --pkg gtk+-2.0
第 1,8 行是 Vala 使用外部函式庫時需要的參數,視實際需求選擇使用
效果相當於
$ valac --pkg gtk+2.0 MyApp.vala
最後是自動產生並修改過後的 configure.ac
#                                               -*- Autoconf -*-
# Process this file with autoconf to produce a configure script.

AC_PREREQ([2.65])
AC_INIT([hello], [0.0], [foo@bar.com])

AM_INIT_AUTOMAKE([-Wall -Werror foreign])

# Checks for programs.
AC_PROG_CC
AM_PROG_VALAC([0.8.0])

# Checks for libraries.
AM_PATH_GTK_2_0                                                 

# Checks for header files.

# Checks for typedefs, structures, and compiler characteristics.

# Checks for library functions.

AC_CONFIG_FILES([Makefile])
AC_OUTPUT
第 14 行會產生出 Makefile.am 所需要的 @GTK_CFLAGS@ 及 @GTK_LIBS@
最後就是一般 GNU Build System 慣用的指令
$ autoreconf -if
$ ./configure
$ make
參考資料:

2010年10月8日 星期五

使用 GNU Build System (aka Autotools) 來管理 Vala 編譯流程

首先要先安裝好需要的軟體套件

以 Ubuntu 10.04 為例
$ sudo apt-get install autoconf automake pkg-config valac vim

Ubuntu 10.04 上面的 Vim 並沒有提供 Vala 的語法著色
還好官方網站上面已經有提供了 Vala/Vim
照著做一遍就好了

準備一個的 hello world 原始碼檔案 hello.vala
void main() {
    stdout.printf("Hello world\n");
}

接者寫一個 Makefile.am
bin_PROGRAMS = hello
hello_SOURCES = hello.vala
hello_CPPFLAGS = @GLIB_CFLAGS@
hello_LDFLAGS = @GLIB_LIBS@

然後將 autoscan 產生出來的 configure.scan 更名為 configure.ac
$ autoscan
$ mv configure.scan configure.ac

再修改成下面這樣
#                                               -*- Autoconf -*-
# Process this file with autoconf to produce a configure script.

AC_PREREQ(2.65)
AC_INIT([hello],[0.0],[foo@bar.com])

AM_INIT_AUTOMAKE([-Wall -Werror foreign])

# Checks for programs.
AC_PROG_CC
AM_PROG_VALAC([0.8.0])

# Checks for libraries.
AM_PATH_GLIB_2_0(,,,[gobject])                                  

# Checks for header files.

# Checks for typedefs, structures, and compiler characteristics.

# Checks for library functions.

AC_CONFIG_FILES([Makefile])
AC_OUTPUT

第 7 行的
AM_INIT_AUTOMAKE([-Wall -Werror foreign])
會產生一些處理 Makefile.am 的工具出來

第 10 行的
AC_PROG_CC
會檢查 C Compiler 因為 Vala 最終還是會產生 C 的原始檔案

第 11 行的
AM_PROG_VALAC([0.8.0])
當然就是檢查這篇文章的主角 Vala 囉

第 14 行的
AM_PATH_GLIB_2_0(,,,[gobject])
會產生出在 Makefile.am 所使用的 @GLIB_CFLAGS@ 跟 @GLIB_LIBS@
還有會使用到 glib 裡面的 gobject 這個 module

接下來就如同一般的 GNU Build System (aka Autotools) 的慣用方法
使用以下命令來產生 configure 腳本檔案
$ autoreconf -if

然後就是 ./configure && make && make install 這類常見的指令連續技囉~ :P