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

2011年7月24日 星期日

關於 uptime 的一些小事

在 GNU/Linux 系統底下如果想要知道電腦開機後使用了多久的時間,可以直接打指令:
$ uptime
 22:35:06 up  6:26,  4 users,  load average: 0.00, 0.03, 0.05
或是利用 /proc/uptime 來取得資料:
$ cat /proc/uptime 
23282.04 41316.79
但是如果想要寫 C 程式來取得資料呢?
我找到一個在 <time.h> 裡面的函式 clock_gettime()
程式碼如下:
#include <stdio.h>
#include <time.h>

int main(int argc, char* argv[])
{
    struct timespec ts;
    if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0) {
        printf("%ld.%ld\n", ts.tv_sec, ts.tv_nsec);
    }
    return 0;                                      
}
在編譯的時候要加上 -lrt 才能通過編譯
$ gcc -Wall -g -lrt uptime.c -o uptime
執行的結果
$ ./uptime 
23637.821285555
因為我想要在 XWindow 底下根據當下的開機時間,製造出新的 XKeyEvent 出來,而所有的 XEvent 都是使用毫秒的時間格式 (ex. 23637821),所以才去找出這個的函式來用。
詳細的使用說明可以看 manpage
$ man clock_gettime

2009年12月14日 星期一

Delegation in C - 在 C 語言當中實作委派方法 (2)

延續前一篇文章的想法 Delegation in C - 在 C 語言當中實作委派方法 (1)
像是
invoke_all_func(&list, "Hello World");
這樣的函式顯然不夠彈性
於是想到一個解決方法就是傳入一個 function pointer 給 invoke_all_func() 於是就變成像是下面這樣
invoke_all_func(&list, my_cb_func, "Hello World");
讓 invoke_all_func() 內部去 callback 這個傳入的 function pointer
再利用 <stdarg.h> 所提供相關的函式將傳入的參數取回
因為只有呼叫 invoke_all_func() 的地方才知道傳入的參數有哪些
所以負責將參數取來出也是相當合理的於是 my_cb_func() 的實作就會像下面這樣
static bool my_cb_func(func_t func, va_list ap)
{
    my_func_t my_func = (my_func_t) func;
    const char* value = va_arg(ap, const char*);
    return my_func(value);
}
其中的 my_func_t 是
typedef bool (*my_func_t)(const char*);
於是就可以定義不一樣的 my_func_t 跟 my_cb_func() 來使用同樣 event bubbling 的方法
達到程式碼可以重複使用的好處
詳細的程式碼實作放在 http://fd.idv.tw/tux/callback.tar.bz2
沒有版權也不負責任更不保證沒有長蟲~ :P

2009年12月13日 星期日

Delegation in C - 在 C 語言當中實作委派方法 (1)

原本的想法是想要能夠在 C 語言中實現 event bubbling
提供一些函式去註冊需要被 callback 的函式
然後在 event 發生時去呼叫所有註冊過的函式
於是就有了以下的程式碼

首先來看一段程式碼片段
int main(int argc, char* argv[])
{
    list_t* list = NULL;

    add_func(&list, funcA);
    add_func(&list, funcB);
    add_func(&list, funcC);

    invoke_all_func(&list, "Hello World");

    return 0;
}
這邊利用 add_func() 將 funcA, funcB, funcC 註冊到某個 double linked list 上面
然後呼叫 invoke_all_func() 去呼叫註冊好的 funcA, funcB, funcC
static bool funcA(const char* str)
{
    fprintf(stderr, "%s says %s\n", __FUNCTION__,  str);
    return true;
}

static bool funcB(const char* str)
{
    fprintf(stderr, "%s says %s\n", __FUNCTION__,  str);
    return true;
}

static bool funcC(const char* str)
{
    fprintf(stderr, "%s says %s\n", __FUNCTION__,  str);
    return true;
}
執行後的結果是
funcC says Hello World
funcB says Hello World
funcA says Hello World
這邊的設計上是越後面註冊的函式越先被呼叫到
如果把 funcC() 的回傳值改成 false 結果就會變成
funcC says Hello World
只要某個註冊過的函式先回傳了 false 接下去的函式就不必再去執行了
於是這兩個負責註冊跟呼叫的函式的 prototype 應該就長得像是下面這樣
bool add_func(list_t** list, bool (*func)(const char*));
bool invoke_all_func(list_t** list, const char* msg);
然後再去實作這些函式的剩餘部份,不過問題來了...
當 funcA, funcB, funcC 換成了
static bool funcA(int val)
{
    fprintf(stderr, "%s count %d\n", __FUNCTION__,  val);
    return true;
}

static bool funcB(int val)
{
    fprintf(stderr, "%s count %d\n", __FUNCTION__,  val);
    return true;
}

static bool funcC(int val)
{
    fprintf(stderr, "%s count %d\n", __FUNCTION__,  val);
    return true;
}
或者是換成了
static bool funcA(const char* msg, int val)
{
    fprintf(stderr, "%s says '%s' count: %d\n", __FUNCTION__, msg, val);
    return true;
}

static bool funcB(const char* msg, int val)
{
    fprintf(stderr, "%s says '%s' count: %d\n", __FUNCTION__, msg, val);
    return true;
}  

static bool funcC(const char* msg, int val)
{
    fprintf(stderr, "%s says '%s' count: %d\n", __FUNCTION__, msg, val);
    return true;

可是 event bubbling 的方法還是一模一樣的,這時候我們應該怎麼辦呢?
有一種最不用花腦袋最快速可以解決問題的辦法就是去複製貼上程式碼,然後將參數換一換,有幾種不同的函式就重複幾次同樣的工作

待續...