2011-04-22 20 views
1

爲了克服給予C庫回調到C++成員函數的impossibility,要實現這樣的:通過使用地圖,其中包含datahandle的*地址爲索引std :: map,通過指針(指向某個對象的相關結構)存儲指針(指向對象)。使用哪些類型?

SomeObject* findSomeObjectByHandlePointer(datahandle *dh) { }.. 

,和地址* SomeObject的價值。

當創建SomeObject時,它會生成一組數據句柄,它們是對象唯一的。然後,它將一個指向* datahandle和靜態回調函數的指針傳遞給C庫,然後C庫回調並返回一個指向數據句柄的指針,該指針又可以與SomeObject關聯。

除了安全但速度慢的<string, SomeObject*>之外,您還可以推薦哪些類型的指針值存儲在地圖中?


This answer告訴我也要避免使用auto_ptr

+0

也許我錯過了一些東西,但爲什麼回調不能接收一個指向對象本身的指針(轉換爲'void *'),從而避免了任何類型的查找? – 2011-04-22 19:20:48

+0

'string'是如何涉及的? – 2011-04-22 19:23:00

+0

我想你錯過了那篇文章的第一句話。 **不要。** ...如果您必須支持遺留代碼,那麼您可以創建一個全局對象或單例對象,並將方法導出爲頂級非成員函數。 – AJG85 2011-04-22 19:25:01

回答

4

通常情況下,類似C的回調需要一個void* user_data參數,它允許你在任何傳給你想:

void c_func(void (*fptr)(void*), void* user_data){ 
    // do some stuff 
    fptr(user_data); 
} 

現在,只需進行以下靜態成員函數:

class A{ 
public: 
    static void c_callback(void* my_data){ 
    A* my_this = static_cast<A*>(my_data); 
    // do stuff with my_this 
    } 
}; 

編輯:據@馬丁的評論,你可能會得到不吉利與靜態成員函數。更好地使用extern "C"功能: 爲extern 「C」 無效c_callback(無效* my_data){// 一樣的靜態方法 } 並傳遞+您的A實例到c_func

int main(){ 
    A a; 
    c_func(&A::c_callback,&a); 
} 

或者如果A實例需要超出當前作用域,您需要以某種方式將堆分配指針保存在某處並稍後手動將其刪除。不幸的是,shared_ptr或類似的東西在這裏不起作用。 :(


在您的地圖存儲指針的問題,這不是在所有問題,看到這個小example on Ideone

+0

您可以使用'my_this-> callback()',而不是使用'my_this'完成所有工作。 – 2011-04-22 19:23:41

+0

@Mike:包含在'do stuff'中。 ;)就像正常行爲被包含在未定義的行爲中一樣。 – Xeo 2011-04-22 19:25:21

+0

從技術上講,靜態方法有C++調用約定。 C函數(在C庫中)只能使用C調用約定。你很幸運,他們在你的系統上重疊。最好聲明一個外部「C」函數而不是靜態方法。 – 2011-04-22 19:30:20

1

我認爲這就夠了。這就是我們使用:

class datahandle; 
class SomeObject; 

typedef std::map<datahandle*, SomeObject*> pointer_map; 

pointer_map my_map; 

SomeObject* findSomeObjectByHandlePointer(datahandle *dh) { 
    pointer_map::const_iterator ff = my_map.find(dh); 
    if (ff != my_map.end()) { 
     return ii->second; 
    } 
    return NULL; 
} 
+0

datahandle是一個結構..當使用struct *作爲映射索引時,是不是有一種複製/比較值的問題? – 2011-04-22 19:42:01

1

通常回調函數有void*類型,你可以用它來的一個額外的參數所以如果你想使用成員函數作爲你的回調函數,你傳遞一個指向對象的指針,並將其轉換爲void*,然後將它轉換回來並在回調函數中調用成員函數。

1

如果你有很多讀取和更少的寫入,你可以d使用向量作爲一個集合。這是很常見的,因爲lower_boundmap更有效,使用更少的空間從內存:

typedef std::pair<std::string,Your_pointer> your_type; 
bool your_less_function(const your_type &a, const your_type &b) 
{ 
    // your less function 
    return (a < b); 
} 
... 
std::vector<your_type> ordered-vector; 

當您添加值:

... 
ordered-vector.push_back(value) 
... 
// Finally. The vector must be sorted before read. 
std::sort(ordered-vector.begin(), ordered-vector.end(), your_less_function); 

當問數據:

std::vector<your_type>::iterator iter = std::lower_bound(ordered-vector.begin(), ordered-vector.end(), value, your_less_function); 
if ((iter == ordered-vector.end()) || your_less_function(*iter, value)) 
    // you did not find the value 
else 
    // iter contains the value 
相關問題