2011-04-22 107 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