在我的项目中,我想使用C++和STL容器,但有一个问题,我必须包括用ANSI C编写的包含C++的硬件供应商 header (并链接供应商lib并使用一些供应商C源代码,其中还包括供应商 header )保留关键字,例如:
vendor.h:
// Vendor header (read only)
struct Vendor_Export_Struct {
unsigned char* data;
};
struct Vendor_Export_Struct export; // <<< compilation error under C++
union Vendor_Union {
struct Vendor_Export_Struct export; // <<< compilation error under C++
};
C++中包含的内容将在编译期间导致错误:“导出”之前的预期不合格ID。因此,我被迫使用纯C,并考虑是否有可能将STL vector 简单地包装到这种C API中(后面是C++实现):cvect.h:
typedef void* Vect_Type;
typedef void** Vect_Iterator_Type;
typedef void* Vect_Data_Type;
Vect_Type Vect_New();
void Vect_PushBack(Vect_Type v, Vect_Data_Type d);
Vect_Iterator_Type Vect_Begin(Vect_Type v);
Vect_Iterator_Type Vect_End(Vect_Type v);
Vect_Iterator_Type Vect_Next(Vect_Type v, Vect_Iterator_Type it);
但是问题是如何传递 vector 和迭代器。我认为在C++代码端从std::vector <>-> void *-> std::vector <>进行转换时,我仍然会被迫使用reinterpret_cast,并且仍然在考虑如何转换/传递std::vector <>: :iterator。c_vect.cpp:
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <vector>
#include <algorithm>
#include "c_vect.h"
typedef std::vector<void*> Vect_Container_Type;
Vect_Type Vect_New()
{
return static_cast<Vect_Type>(new Vect_Container_Type);
}
void Vect_PushBack(Vect_Type v, Vect_Data_Type d)
{
Vect_Container_Type& vref = *reinterpret_cast<Vect_Container_Type*>(v);
vref.push_back(d);
}
Vect_Iterator_Type Vect_Begin(Vect_Type v)
{
Vect_Container_Type& vref = *reinterpret_cast<Vect_Container_Type*>(v);
return &*vref.begin();
}
Vect_Iterator_Type Vect_End(Vect_Type v)
{
Vect_Container_Type& vref = *reinterpret_cast<Vect_Container_Type*>(v);
return &*vref.end();
}
Vect_Iterator_Type Vect_Next(Vect_Type v, Vect_Iterator_Type it)
{
Vect_Container_Type& vref = *reinterpret_cast<Vect_Container_Type*>(v);
Vect_Container_Type::iterator it_ = static_cast<Vect_Container_Type::iterator>(it); //<<<< ugly and not portable
if (it_ != vref.end())
{
++it_;
return &*it_;
}
return NULL;
}
main.c:#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "c_vect.h"
#include "vendor.h"
typedef struct S_Connection {
size_t id;
char* name;
union Vendor_Union u;
Vect_Type sessions; // Another vector
} T_Connection;
typedef T_Connection* T_ConnectionPtr;
static void* makeConn(size_t id, const char* name)
{
T_ConnectionPtr ptr = (T_ConnectionPtr)malloc(sizeof(T_Connection));
ptr->id = id;
ptr->name = (char*)malloc(strlen(name) + 1);
strcpy(ptr->name, name);
return ptr;
}
int main(int argc, char* argv[])
{
Vect_Type conns = Vect_New();
Vect_Iterator_Type it;
unsigned i;
for (i = 0; i < 10; ++i) {
char name[20];
sprintf(name, "conn_%03d", i);
Vect_PushBack(conns, makeConn(i + 1, name));
}
// Iterate vector and access stored data
for (it = Vect_Begin(conns);
it != Vect_End(conns);
it = Vect_Next(conns, it)) {
T_ConnectionPtr cd = (T_ConnectionPtr)*it;
}
return 0;
}
因此,我不确定这是否是个好主意,可能不是出于几个原因。我只是想避免其他冗余的C vector 实现,请从STL迭代器中获利。最终代码应该是可移植的。有人正在解决类似的问题吗?还是您有一个更好的主意该如何应对?
最佳答案
现在有一些方法可以访问Vector的原始数据数组:
value_type* data() noexcept;
const value_type* data() const noexcept;
这些扩展正是针对您的情况在C++ 11中添加的,以连接仅采用原始数据数组的第三方库。将返回的指针作为数组传递给C,该数组也是C中的指针。您可能需要添加vector.size()作为另一个参数。使用返回的指针时不要操纵 vector 。
关于c++ - 如何包装std::vector以在纯C中使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62789873/