學習DirectFB之:編譯運行第一個DirectFB程序

摘要:

本文介紹瞭如果把一個DirectFB源程序文件編譯一個可執行的文件,附帶性的介紹了gcc的常見編譯選項的應用。


---------------------------------------------------------------------------------------------------------------------
聲明:
       此文爲原創,歡迎轉載,轉載請保留如下信息
       作者:聶飛(afreez)
       聯繫方式:[email protected] (歡迎與作者交流)
       初次發佈時間:2006-05-29
      不經本人同意,不得用語商業或贏利性質目的,否則,作者有權追究相關責任!
---------------------------------------------------------------------------------------------------------------------
  

編程環境:

調試環境:FC5(Fedora Core 5)、DirectFB.0.9.24或DirectFB.0.9.25

安裝信息:DirectFB不是默認的安裝方式,安裝路徑爲/usr/DirectFB25/

 

DirectFB源程序

程序名:draw_line.c

功能:在屏幕中間畫一條水平直線

 

#include <stdio.h>

#include <unistd.h>

 

#include <directfb.h>

 

//這是最上層的接口,所有的函數入口均由它(IDirectFB)而來

static IDirectFB *dfb = NULL;

 

//主平面,也就是“屏幕”了。在交互層使用DFSCL_FULLSCREEN,它是主層平面。

static IDirectFBSurface *primary = NULL;

 

//這裏存儲主平面的高和寬,從而爲其它的操作提供支持

static int screen_width  = 0;

static int screen_height = 0;

 

//用以檢測錯誤的宏定義,用來檢測大部分的函數的返回值是否正常。只適合用在小的測試程序

#define DFBCHECK(x...)  /

{                /

       DFBResult err = x;   /

       /

         if (err != DFB_OK)  /

         {  /

                fprintf( stderr, "%s <%d>:/n/t", __FILE__, __LINE__ ); /

               DirectFBErrorFatal( #x, err );  /

        } /

}

 

 

int main (int argc, char **argv)

{

       //爲了創建一個平面,需要定義一個平面描述子(surface description

DFBSurfaceDescription dsc;

//初始化

    DFBCHECK (DirectFBInit (&argc, &argv));

       DFBCHECK (DirectFBCreate (&dfb));

       DFBCHECK (dfb->SetCooperativeLevel (dfb, DFSCL_FULLSCREEN));

 

       //設定dsc的一些屬性,現在可以不用關心

       dsc.flags = DSDESC_CAPS;

       dsc.caps  = DSCAPS_PRIMARY | DSCAPS_FLIPPING;

 

       //使用我們設定的dsc創建主平面(primary)

       DFBCHECK (dfb->CreateSurface( dfb, &dsc, &primary ));

       //得到主平面的寬與高

       DFBCHECK (primary->GetSize (primary, &screen_width, &screen_height));

       //通過畫一個和主平面同等大小的矩形來清空主平面;默認顏色爲黑色

       DFBCHECK (primary->FillRectangle (primary, 0, 0, screen_width, screen_height));

       //爲了能顯示畫出來的線,先設置一下線的顏色,線的位置在屏幕的中間

DFBCHECK (primary->SetColor (primary, 0x80, 0x80, 0xff, 0xff));

       DFBCHECK (primary->DrawLine (primary,0, screen_height / 2,screen_width - 1, screen_height / 2));

 

       //顯示

       DFBCHECK (primary->Flip (primary, NULL, 0));

 

       //等待5秒後,程序自動退出

       sleep (5);

       primary->Release( primary );

       dfb->Release( dfb );

       return 23;

}

 

編譯準備

安裝完DirectFB後,由於某種原因,我沒有把/usr/DirectFB25/lib添加到配置文件/etc/ld.so.conf 中,所以,在進入(每一個)終端時,要設置兩個環境變量,如下所示:

$export PKG_CONFIG_PATH=/usr/DirectFB25/lib/pkgconfig/

$export LD_LIBRARY_PATH=/usr/DirectFB25/lib

 

編譯

爲了詳細分析其編譯過程,先分析幾個使用不當的編譯過程,最後給出兩中常用的編譯方法。

不當編譯1:$gcc draw_line.c -o draw_line

正常情況下,我們做一些練習時,常常使用如下的編譯格式來編譯:

$gcc src.c –o destination

如果這裏,我們同樣使用這樣的編譯選項時,會出現類似如下的編譯錯誤:

 

draw_line.c:3:22: error: directfb.h: No such file or directory

draw_line.c:4: error: expected '=', ',', ';', 'asm' or '__attribute__' before '*' token

draw_line.c:5: error: expected '=', ',', ';', 'asm' or '__attribute__' before '*' token

draw_line.c: In function 'main':

draw_line.c:20: error: 'DFBSurfaceDescription' undeclared (first use in this function)

draw_line.c:20: error: (Each undeclared identifier is reported only once

draw_line.c:20: error: for each function it appears in.)

draw_line.c:20: error: expected ';' before 'dsc'

draw_line.c:21: error: 'DFBResult' undeclared (first use in this function)

draw_line.c:21: error: expected ';' before 'err'

……

 

錯誤中顯示了很多編譯異常輸出,最讓人無法忍受的是竟然沒有找到頭文件directfb.h,編譯DirectFB應用程序,可基本上都需要這個頭文件的!怎麼會找不到呢?

使用$ls /usr/DirectFB25/include/directfb  查看一下,發現裏面確實有directfb.h。那麼,就是GCC沒有找到該文件了,也就是說,gcc默認查找庫文件的路徑不包括:

/usr/DirectFB25/include/directfb

該路徑是我安裝的目錄,如果不通知gcc的話,它是不會去這裏找相關庫文件及頭文件的。

好了,知道了異常輸出的原因之後,我們改用下面的編譯命令進行編譯。

 

不當編譯2:

$gcc -L/usr/DirectFB25/lib -I/usr/DirectFB25/include/directfb  draw_line.c -o draw_line

查看相關的gcc編譯參數,我們可以知道其中的-L與-I的含義,相關含義大致如下:

-I(大寫的i)參數是用來指定頭文件目錄,/usr/include目錄一般是不用指定的,gcc知道去那裏找,但是如果頭文件不在/usr/include裏我們就要用-I參數指定了,比如頭文件放在/not_usr目錄裏,那編譯命令行就要加上- I/not_usr參數了,如果不加你會得到一個類似上面的異常輸出。-I參數可以用相對路徑,比如頭文件在當前目錄,可以用-I.來指定。

-l(小寫的L)參數就是用來指定程序要鏈接的庫,-l參數緊接着就是庫名。當我們自已要用到一個第三方提供的庫名字libtest.so,那麼我們只要把libtest.so拷貝到 /usr/lib裏,編譯時加上-ltest參數,我們就能用上libtest.so庫了(當然要用libtest.so庫裏的函數,我們還需要與 libtest.so配套的頭文件)。

放在/lib和/usr/lib和/usr/local/lib裏的庫直接用-l參數就能鏈接了,但如果庫文件沒放在這三個目錄裏,而是放在其他目錄裏,這時我們只用-l參數的話,鏈接還是會出錯,出錯信息大概是:“/usr/bin/ld: cannot find -lxxx”,也就是鏈接程序ld在那3個目錄裏找不到libxxx.so,這時另外一個參數-L就派上用場了,比如常用的X11的庫,它在 /usr/X11R6/lib目錄下,我們編譯時就要用-L/usr/X11R6/lib -lX11參數,-L參數跟着的是庫文件所在的目錄名。再比如我們把libtest.so放在/aaa/bbb/ccc目錄下,那鏈接參數就是- L/aaa/bbb/ccc –ltest。

可是,即使這樣來編譯,還是會出現如下的類似異常輸出信息,大致如下:

 

/tmp/cc4yJt2K.o: In function `main':draw_line.c:(.text+0x1e): undefined reference to `DirectFBInit'

:draw_line.c:(.text+0x5f): undefined reference to `DirectFBErrorFatal'

:draw_line.c:(.text+0x6b): undefined reference to `DirectFBCreate'

:draw_line.c:(.text+0xac): undefined reference to `DirectFBErrorFatal'

:draw_line.c:(.text+0x107): undefined reference to `DirectFBErrorFatal'

:draw_line.c:(.text+0x178): undefined reference to `DirectFBErrorFatal'

:draw_line.c:(.text+0x1db): undefined reference to `DirectFBErrorFatal'

:draw_line.c:(.text+0x255): undefined reference to `DirectFBErrorFatal'

/tmp/cc4yJt2K.o:draw_line.c:(.text+0x2c8): more undefined references to `DirectFBErrorFatal' follow

collect2: ld returned 1 exit status

 

這次,頭文件directfb.h是找到了,可是,好多庫的接口函數卻沒有找到!注意,此時的輸出都是連接錯誤,已經沒有了語法錯誤了。也就是說,我們寫的這個draw_line.c源文件已經通過了預編譯、編譯和彙編階段,只是最後的連接過程出現了異常。Gcc的處理過程會經歷四個過程,分別爲∶預處理(也稱 預編譯,Preprocessing)、編譯(Compilation)、彙編(Assembly)和連接(Linking),詳細介紹見相關資料。

也就是說,我們現在只要解決連接的問題就ok了。那麼如何才能找到我們需要的函數庫的接口呢?

如果你足夠仔細的話,在安裝DirectFB提供的事例(如:DirectFB-examples-0.9.23.tar.gz)的時候,其中會提級到一個文件,即directfb.pc。該文件記錄了你的一些安裝信息,現在讓我們來看看它裏面的內容把。

$ more /usr/DirectFB25/lib/pkgconfig/directfb.pc

 

prefix=/usr/DirectFB25

exec_prefix=${prefix}

libdir=${exec_prefix}/lib

includedir=${prefix}/include

 

Name: DirectFB

Description: Graphics and windowing library for the Linux frame buffer device

Version: 0.9.25

Requires: fusion direct

Libs: -L${libdir} -ldirectfb -lpthread -ldl -lz

Cflags: -D_REENTRANT -I${prefix}/include/directfb

 

裏面詳細記錄了我們安裝的路徑、版本以及庫的信息。特別注意裏面有一行爲:

Libs: -L${libdir} -ldirectfb -lpthread -ldl -lz

乖乖,終於找到它了,呵呵。好了,我們再來編譯一下把。

 

正確的編譯方式1

$ gcc -L/usr/DirectFB25/lib -I/usr/DirectFB25/include/directfb -ldirectfb -lpthread -ldl -lz  draw_line.c -o draw_line

編譯後,再也沒有異常輸出信息了,好了。終於成功了,還等什麼?先去運行一下,看看效果吧!

 

如果你已經欣賞完了你“自己”畫的那條直線的話,那麼,我們再來看看另一種簡便的編譯方法。

正確的編譯方式2

$gcc `pkg-config --cflags --libs directfb` -o draw_text draw_text.c

注意,這裏的pkg-config --cflags --libs directfb兩側使用的不是單引號,而是鍵盤上數字鍵1左邊的那個和“~”一體的“`”鍵符號;--libs 後面的包名directfb也不要忘記寫,否則會出下類似如下的錯誤信息:

 

Package directfb was not found in the pkg-config search path.

Perhaps you should add the directory containing `directfb.pc'

to the PKG_CONFIG_PATH environment variable

No package 'directfb' found

 

在編譯DirectFB應用程序和庫的時候,pkg-config是一個十分有用的工具,關於pkg-config的使用方法,詳見:

http://pkgconfig.freedesktop.org/wiki/

 

補充:

如果你安裝的版本是DirectFB.0.9.25的話,在你用gcc編譯時,可能會出現找不到libdirect-0.9.so.24或libdirectfb-0.9.so.24或libfusion-0.9.so.24的情況(反正我的機器是出現了)。查看你的libs位置:

$ls /usr/DirectFB25/lib

你會發現,其中的庫的版本都是*.so.25,鬼才能找到什麼*.so.24的連接庫。不過,也沒有關係了,有條件要上,沒有條件,創造條件,也要上了。來,自己動手,豐衣足食吧。

$cd /usr/DirectFB25/lib

ln -s libdirect-0.9.so.25.0.0 libdirect-0.9.so.24

ln -s libdirectfb-0.9.so.25.0.0 libdirectfb-0.9.so.24

ln -s libfusion-0.9.so.25.0.0 libfusion-0.9.so.24

 

Reference:

1.       本文中的DirectFB畫線應用程序來自:

http://www.directfb.org/docs/DirectFB_Tutorials/simple.html

2.Man page of gcc  使用$man gcc查看

3.Gcc相關的中文介紹,參照:

http://www.raidcheng.net/blog/archives/2005/03/

http://www.linuxeden.com/doc/20454.html



本文轉自:http://blog.csdn.net/ganxingming/article/details/761932



發佈了12 篇原創文章 · 獲贊 1 · 訪問量 9萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章