2009-01-27 104 views
11

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

#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: error: invalid conversion from 'void*' to 'double (*)(double)'

我瞭解(我認爲我明白,如果指正這是錯誤的),我不能在C++中使用void指針進行隱式轉換,但C讓我,這就是爲什麼上面的代碼將使用gcc編譯而不是使用usin g g ++。因此,我通過改變上述行16試過一個顯式的:

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

有了這個地方,我得到以下錯誤:

foo.cpp:16: error: cannot convert 'double*' to 'double (*)(double)' in assignment

這些問題可能有更多的事情要做我自己一般的無知適當的C++編碼標準。任何人都可以點我一個關於開發使用C++示例代碼的Linux動態庫的好教程嗎?

+0

我建議通過「在C++中思考」來加快C++的速度。正如你正確的發現,你不能隱式地從void *轉換到C++中的其他指針,這意味着你真的只需要在C++而不是其他區域上加快速度:) – workmad3 2009-01-27 15:34:14

+0

謝謝,我正在閱讀C++ Primer在業餘時間,但現在我有一個項目到期。 – 2009-01-27 15:36:12

回答

24

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"); 
9

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) 

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

+0

您的函數指針聲明不是。 – Arkadiy 2009-01-27 15:41:53

+0

這適用於double(* cosine)(double);從原始代碼,但不是你提供的函數指針聲明。由於我是一個無知的人在這裏提問,我不認爲我應該改變你的代碼。 :) – 2009-01-27 15:46:27

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

  • 替換而過時的fputs消息,一個std :: CERR或std ::法院:

    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++代碼中,並且工作得很好。這個函數指針的情況是一個例外。