在 C 中迭代 C++ 容器
Iterate over a C++ container in C
我正在尝试为某些 C++ 数据结构编写 C 包装器。现在我在 foo.cpp
中得到以下内容
typedef std::map<unsigned int, void *> _Map;
extern "C"{
void* map_create()
{
return reinterpret_cast<void*> (new _Map);
}
void map_put(void *map, unsigned int k, void *v)
{
Map *m = reinterpret_cast<_Map *> (map);
m->insert(std::pair<unsigned int, void *>(k, v));
}
}
在 foo.h
我有
#ifdef __cplusplus
#define EXTERNC extern "C"
#else
#define EXTERNC
#endif
typedef void *Map;
EXTERNC void *map_create();
EXTERNC void map_put(void* map, unsigned int k, int v);
我包括 foo.h
,我很高兴。
现在,我想遍历映射并注意到 C++ 通过迭代器来实现。我没有使用 C++ 的经验,也不知道迭代器是如何实现的。
我可以使用 C 包装器迭代 std::map
吗?这些函数定义看起来如何,我将如何在我的 C 代码的 for 循环中使用它们?
您将无法直接使用迭代器。当然,您 可以 ,按照 creating/releasing 对象的方式做一些事情并以某种方式获取值。但是,它不会有效率。它看起来像这样:
typedef std::map<unsigned int, void*> map_type;
typedef map_type::iterator map_iterator;
void* map_iterator_create(void* map) {
return new map_iterator(map.begin());
}
void map_iterator_destroy(void* it) {
delete static_cast<map_iterator*>(it);
}
int map_iterator_next(void* map, void* it, unsigned int* key, void** value) {
map_iterator* mit = static_cast<map_iterator*>(it);
if (static_cast<map_type*>(map)->end() == *mit) {
return 0; // no more elements
}
*key = mit->first;
*value = mit->second;
++mit;
return 1;
}
这种特殊方法确实会稍微降低迭代器带来的灵活性(例如,它不支持子范围),但可以以不同的成本支持这些方法。您将像这样使用此迭代器方法:
void* it = map_iterator_create(map);
unsigned int key;
void* value;
while (map_iterator_next(map, it, &key, &value)) {
printf("key=%d value=%p\n", key, value);
}
map_iterator_destory(it);
不公开迭代器接口而是公开迭代序列的接口可能更合理,例如:
extern "C" { typedef void (*map_function)(unsigned int, void*, void*); }
void map_iterate(void* map, map_function fun, void* userdata) {
map_type* m = static_cast<map_type*>(m);
std::for_each(m->begin(), m->end(),
[=](map_type::value_type const& v) {
fun(v.first, v.second, userdata);
});
}
... 将用作
void my_iterating_fun(unsigned int key, void* value, void* userdata) {
printf("key=%d value=%p\n", key, value);
}
// ...
map_iterator(map, my_iterating_fun, 0);
我没有尝试编译代码(即,它可能充满了小拼写错误),但按照这些思路应该可以工作。
有些东西无法编译,但可以让您了解我将如何编译
class MyIterator {
public:
MyIterator(Map map) {
it = map.begin();
}
void advance() {
++it;
}
bool isValid() {
return it != map.end();
}
private:
Map::const_iterator it;
const Map map;
};
extern "C" {
void* newIterator(void* map) {
return new MyIterator(static_cast<Map>(map));
}
void freeIterator(void* it) {
delete static_cast<Map>(map);
}
void advanceIterator(void* it) {
static_cast<MyIterator>(it)->advance();
}
void isValid(void* it) {
static_cast<MyIterator>(it)->isValid();
}
int getKey(void* iterator) {...}
void* getValue(void* iterator) {...}
}
我正在尝试为某些 C++ 数据结构编写 C 包装器。现在我在 foo.cpp
typedef std::map<unsigned int, void *> _Map;
extern "C"{
void* map_create()
{
return reinterpret_cast<void*> (new _Map);
}
void map_put(void *map, unsigned int k, void *v)
{
Map *m = reinterpret_cast<_Map *> (map);
m->insert(std::pair<unsigned int, void *>(k, v));
}
}
在 foo.h
我有
#ifdef __cplusplus
#define EXTERNC extern "C"
#else
#define EXTERNC
#endif
typedef void *Map;
EXTERNC void *map_create();
EXTERNC void map_put(void* map, unsigned int k, int v);
我包括 foo.h
,我很高兴。
现在,我想遍历映射并注意到 C++ 通过迭代器来实现。我没有使用 C++ 的经验,也不知道迭代器是如何实现的。
我可以使用 C 包装器迭代 std::map
吗?这些函数定义看起来如何,我将如何在我的 C 代码的 for 循环中使用它们?
您将无法直接使用迭代器。当然,您 可以 ,按照 creating/releasing 对象的方式做一些事情并以某种方式获取值。但是,它不会有效率。它看起来像这样:
typedef std::map<unsigned int, void*> map_type;
typedef map_type::iterator map_iterator;
void* map_iterator_create(void* map) {
return new map_iterator(map.begin());
}
void map_iterator_destroy(void* it) {
delete static_cast<map_iterator*>(it);
}
int map_iterator_next(void* map, void* it, unsigned int* key, void** value) {
map_iterator* mit = static_cast<map_iterator*>(it);
if (static_cast<map_type*>(map)->end() == *mit) {
return 0; // no more elements
}
*key = mit->first;
*value = mit->second;
++mit;
return 1;
}
这种特殊方法确实会稍微降低迭代器带来的灵活性(例如,它不支持子范围),但可以以不同的成本支持这些方法。您将像这样使用此迭代器方法:
void* it = map_iterator_create(map);
unsigned int key;
void* value;
while (map_iterator_next(map, it, &key, &value)) {
printf("key=%d value=%p\n", key, value);
}
map_iterator_destory(it);
不公开迭代器接口而是公开迭代序列的接口可能更合理,例如:
extern "C" { typedef void (*map_function)(unsigned int, void*, void*); }
void map_iterate(void* map, map_function fun, void* userdata) {
map_type* m = static_cast<map_type*>(m);
std::for_each(m->begin(), m->end(),
[=](map_type::value_type const& v) {
fun(v.first, v.second, userdata);
});
}
... 将用作
void my_iterating_fun(unsigned int key, void* value, void* userdata) {
printf("key=%d value=%p\n", key, value);
}
// ...
map_iterator(map, my_iterating_fun, 0);
我没有尝试编译代码(即,它可能充满了小拼写错误),但按照这些思路应该可以工作。
有些东西无法编译,但可以让您了解我将如何编译
class MyIterator {
public:
MyIterator(Map map) {
it = map.begin();
}
void advance() {
++it;
}
bool isValid() {
return it != map.end();
}
private:
Map::const_iterator it;
const Map map;
};
extern "C" {
void* newIterator(void* map) {
return new MyIterator(static_cast<Map>(map));
}
void freeIterator(void* it) {
delete static_cast<Map>(map);
}
void advanceIterator(void* it) {
static_cast<MyIterator>(it)->advance();
}
void isValid(void* it) {
static_cast<MyIterator>(it)->isValid();
}
int getKey(void* iterator) {...}
void* getValue(void* iterator) {...}
}