簡體   English   中英

使用g ++進行動態共享庫編譯

[英]Dynamic Shared Library compilation with g++

我正在嘗試使用g ++從Program-Library-HOWTO編譯以下簡單的DL庫示例代碼。 這只是一個例子,所以我可以學習如何使用和編寫共享庫。 我正在開發的庫的真正代碼將用C ++編寫。

#include <stdlib.h>
#include <stdio.h>
#include <dlfcn.h>

int main(int argc, char **argv) {
    void *handle;
    double (*cosine)(double);
    char *error;

    handle = dlopen ("/lib/libm.so.6", RTLD_LAZY);
    if (!handle) {
        fputs (dlerror(), stderr);
        exit(1);
    }

    cosine = dlsym(handle, "cos");
    if ((error = dlerror()) != NULL)  {
        fputs(error, stderr);
        exit(1);
    }

    printf ("%f\n", (*cosine)(2.0));
    dlclose(handle);
}

如果我用gcc編譯程序,它工作正常。

gcc -o foo foo.c -ldl

當我將文件名和編譯器更改為以下內容時

g++ -o foo foo.cpp -ldl

我收到以下錯誤:

foo.cpp:16:錯誤:無效轉換為'void *'到'double(*)(double)'

我理解(我我理解,如果這是錯的,請糾正我)我不能從C ++中的void指針進行隱式轉換,但C讓我,這就是為什么上面的代碼將使用gcc編譯但不使用克++。 所以我嘗試通過將上面的第16行更改為:

cosine = (double *)dlsym(handle, "cos");

有了這個,我收到以下錯誤:

foo.cpp:16:錯誤:在賦值時無法將'double *'轉換為'double(*)(double)'

這些問題可能與我自己對正確的C ++編碼標准的普遍無知有關。 任何人都可以向我指出一個關於使用C ++示例代碼開發Linux動態庫的好教程嗎?

C允許從void *到任何指針類型(包括函數指針)的隱式轉換; C ++需要顯式轉換。 正如leiflundgren所說,你需要將dlsym()的返回值強制轉換為你需要的函數指針類型。

很多人發現C的函數指針語法很尷尬。 一種常見的模式是typedef函數指針:

typedef double (*cosine_func_ptr)(double);

您可以將函數指針變量cosine定義為您的類型的成員:

cosine_func_ptr cosine;

並使用類型而不是笨拙的函數指針語法進行強制轉換:

cosine = (cosine_func_ptr)dlsym(handle, "cos");

dlsym返回指向符號的指針。 (作為void*是通用的。)在你的情況下,你應該將它強制轉換為函數指針。

 double (*mycosine)(double); // declare function pointer
 mycosine = (double (*)(double)) dlsym(handle, "cos"); // cast to function pointer and assign

 double one = mycosine(0.0); // cos(0)

所以這種罕見的情況之一,編譯器錯誤是一個很好的線索。 ;)

如果編寫代碼的方式,這實際上更像是一個C問題,但你可以使用C ++。 我沒有關於動態共享庫的教程(你鏈接到的網頁似乎很好),但是這里是如何用C ++修復你的代碼:

  • 聲明my_cos是一個將(最終)調用動態加載的余弦函數的函數:

     double my_cos(double); 
  • 將函數指針指定給my_cos

     my_cos = (double (*)(double)) dlsym(handle, "cos"); 

這有點復雜,但它為my_cos分配一個返回double的東西,是取消引用另一個函數指針的結果,並將double作為參數。 正如其他人發布的那樣,C ++對代碼的顯式性的要求比C要高一些。

  • 用std :: cerr或std :: cout替換那個相當過時的fputs消息:

     std::cerr << "error loading library cos: " << error << std::endl; 

std::cout << "result is " << (*my_cos)(2.0)) << std::endl;

希望對此有所幫助。 如果那些怪異的頑皮東西嚇到你,我會推薦van Linden的Deep C Secrets,以及C上的Kernighan和Ritchie Book。

編輯:關於如何專門在C ++而不是C中尋找開發指南的評論中的好點,以避免此類問題。 我不知道C ++中的類似指南,但大約99%的C代碼可以嵌入到C ++代碼中並且工作得很好。 此函數指針大小寫是例外之一。

在C ++中,您必須執行reinterpret_cast (而不是C強制轉換):

typedef double (* double_from_double_function_t(double));
…
double_from_double_function_t cosine = reinterpret_cast<double_from_double_function_t>(dlsym(handle, "cos"));

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM