2009-07-08 111 views
28

我有一個由dlsym()返回的void指針,我想調用void指針指向的函數。 所以我做一個類型轉換通過鑄造:函數指針在C++中鑄造

void *gptr = dlsym(some symbol..) ; 
typedef void (*fptr)(); 
fptr my_fptr = static_cast<fptr>(gptr) ; 

我也曾嘗試reinterpret_cast,但沒有運氣,雖然C轉換運算符似乎工作..

+0

哎,你的格式有陷入困境。 – 2009-07-08 06:11:19

+0

您確實需要修正該代碼,以便我們可以閱讀它。什麼是反斜槓?您是否嘗試輸入my_fptr = static_cast (gptr)? – 2009-07-08 06:11:41

+1

修復了格式問題。而不是使用HTML標記,請使用可用的格式化按鈕。 – Naveen 2009-07-08 06:14:13

回答

45

轉換一個void*一個函數指針直接在C++ 98/03中是不允許的(不應該使用任何強制轉換)。它有條件地支持C++ 0x(一個實現可以選擇定義行爲,如果它確實定義了它,那麼它必須執行標準所說的它應該做的事情。由C++ 98/03標準定義的一個void* ,是爲了指向對象,而不是包含函數指針或成員指針。

知道你在做什麼很大程度上依賴於實現,這裏有一個選項應該是編譯和工作的(假設32位指針,使用long long對於64位)在大多數平臺上,即使它顯然是根據標準定義的操作:

void *gptr = dlsym(some symbol..) ; 
typedef void (*fptr)(); 
fptr my_fptr = reinterpret_cast<fptr>(reinterpret_cast<long>(gptr)) ; 

這裏是應該編譯和工作,但卡爾另一種選擇它IES相同的警告如上述:

fptr my_ptr = 0; 
*reinterpret_cast<void**>(&my_ptr) = gptr; 

或者,在慢動作......

// get the address which is an object pointer 
void (*(*object_ptr))() = &my_ptr; 

// convert it to void** which is also an object pointer 
void ** ppv = reinterpret_cast<void**>(object_ptr); 

// assign the address in the memory cell named by 'gptr' 
// to the memory cell that is named by 'my_ptr' which is 
// the same memory cell that is pointed to 
// by the memory cell that is named by 'ppv' 
*ppv = gptr; 

它本質上利用了這一函數指針的地址是一個對象指針[void (*(*object_ptr))()] - 因此我們可以使用reinterpret_cast將其轉換爲任何其他對象指針:例如void**。然後,我們可以按照地址返回(通過取消引用void **)到實際的函數指針並將gptr的值存儲在那裏。

yuk - 絕不是定義明確的代碼 - 但它應該完成您期望它在大多數實現中執行的操作。

+1

我希望這就是它 - C++鑄造符合標準,C casting正在向後兼容POSIX共享庫調用的要求。 – 2009-07-08 06:16:19

-6

這可能對你有所幫助。它打印「你好」。

#include <iostream> 

void hello() 
{ 
    std::cout << "Hello" << std::endl; 
} 

int main() { 
    typedef void (*fptr)(); 
    fptr gptr = (fptr) (void *) &hello; 
    gptr(); 
} 

或者你可以這樣做:

fptr gptr = reinterpret_cast<fptr>((void *) &hello); 

其中&你好通過對dlsym命令取代。

2

這將編譯在Visual Studio中不使用重新詮釋投:

void *ptr; 
int (*func)(void) = (int(*)(void))ptr; 
int num = func(); 
0

,我發現這個(有點難看)解決方案。具有最大警告級別的gcc不會抱怨。 本示例調用dlsym()(返回void *)並將結果返回給函數指針。

typedef void (*FUNPTR)(); 

FUNPTR fun_dlsym(void* handle, const char* name) { 
    union { 
     void* ptr; 
     FUNPTR fptr; 
    } u; 
    u.ptr = dlsym(handle, name); 
    return u.fptr; 
}