linux平臺 使用dlopen接口調用HelloWorld動態庫簡單實例

動態庫(libxxx.so)一種調用方式是在編譯的時候的時候指定庫名 -lxxx,另一種調用方式是通過dlopen在程序里加載動態庫,然後調用相關接口。相關接口比較簡單,包括打開動態庫,解析庫裏提供的symbol(函數或者變量),關閉動態庫引用計數。

編譯的時候加上-ldl(指定dl庫)
頭文件
#include <dlfcn.h>
/**
 *  加載指定的動態庫並返回動態庫的句柄。如果參數filename爲NULL
 *  則返回的句柄就是main program.如果加載的庫又依賴其它的動態庫
 *  則這些庫會自動被鏈接器加載。
 *  flags有如下選項,可以ORed方式選擇多個
 *  RTLD_LAZY : 在dlopen返回前,對於動態庫中的未定義的符號不執行解析(只對函數引用有效,對於變量引用總是立即解析)。
 *  RTLD_NOW : 需要在dlopen返回前,解析出所有未定義符號,如果解析不出來,在dlopen會返回NULL,錯誤爲:: undefined symbol: xxxx.......
 *  RTLD_GLOBAL:動態庫中定義的符號可被其後打開的其它庫解析。
 *  RTLD_LOCAL:動態庫中定義的符號可被其後打開的其它庫解析。
 *  成功返回非NULL句柄,失敗返回NULL;
 */
void *dlopen(const char *filename, int flags);

/**
 *  減少共享庫句柄的引用計數,如果系統中沒有其它引用的地方,則卸載該庫。
 *  成功返回0,失敗返回非零值。
 */
int dlclose(void *handle);

/**
 *  從dlopen返回的句柄中查找指定的符號並返回地址,
 *  成功返回該符號地址,失敗返回NULL。
 */
void *dlsym(void *handle, const char *symbol);

libHelloWorld.so實現代碼:

//實現文件 HelloWorld.c
/**
 *  簡單動態庫文件使用
 */
#include "HelloWorld.h"

void hello(void)
{
    printf("Hello World \r\n");
    return ;
}

//頭文件 HelloWorld.h
#include <stdio.h>

void hello(void);

dlopen測試程序:

/**
 *  linux平臺 dlopen接口調用動態庫簡單例子
 */
#include <dlfcn.h>
#include <stdlib.h>
#include <stdio.h>

void main()
{
    void *handle;
    void (*hello)(void);

    /* 加載libHelloWorld.so */
    handle = dlopen("libHelloWorld.so", RTLD_LAZY);
    if (!handle) 
    {
        printf("open libHelloWorld.so fail\r\n");
        return;
    }

    /* 引用庫提供的symbol,可以是變量也可以是函數 */
    hello = dlsym(handle, "hello");
    if ( !hello )
    {
        printf("open symbol fail\r\n");
        dlclose(handle);
        return;
    }

    /* 調用庫函數 */
    hello();

    /* 釋放庫的引用計數 */
    dlclose(handle);

    return;
}

Makefile:

#
# Linux dlopen接口調用動態庫簡單例子
#

# -shared 指定生成動態鏈接庫
# -fPIC :表示編譯爲位置獨立的代碼,用於編譯共享庫
dynlib:
	gcc -shared -fPIC -o libHelloWorld.so HelloWorld.c
	cp -rf libHelloWorld.so /usr/lib/

#使用dlopen接口需要在編譯的時候加上-ldl選項
dllib:
	gcc -o dllib dl_call_lib.c  -ldl

clean:
	rm -rf *.o *.so demoapp

測試截圖:

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章