c++ - 如何包装std::vector以在纯C中使用

标签 c++ c iterator stdvector

在我的项目中,我想使用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/

相关文章:

c# - 双重使用 C# 迭代器工作意外

python - 为什么可迭代对象不是迭代器?

c++ - linux C++定时器周期回调

c++ - 是否有更多 C++ 方法来获取 EOF 代码?

c - 计算 C 代码的圈复杂度的工具

c - 如何计算数据包有效负载中的字节数?

c++ - R data.table和STRING_ELT()错误:如何修复 'character vector' vs 'char'错误?

c++ - 在 C++ 中的模板化基类中查找名称

c - 将两个文本文件中的两个矩阵相乘,输出为零

C++ Primer 第 5 版练习 3.24 - vector 中的迭代器