我可以为任何可以放入 Extern C 的 C++ 向量制作一个 C 包装器吗

Posted

技术标签:

【中文标题】我可以为任何可以放入 Extern C 的 C++ 向量制作一个 C 包装器吗【英文标题】:Can I make one C wrapper for any C++ vector that could go in a Extern C 【发布时间】:2014-03-28 04:35:06 【问题描述】:

我需要一个用于任何 C++ 向量的 C 包装器,它可以传递给需要某种特定类型向量的函数。就像我下面的 OpenCV 的 BRISK 的 C 包装器一样”

void cv_BRISK_generateKernel(BRISK* self, vector_float* radiusList, 
vector_int* numberList, float dMax, float dMin, vector_int* indexChange) 
        self->generateKernel(*radiusList, *numberList, dMax, dMin, *indexChange);

vector_int*vector_float*typedef,如下所示

typedef vector<int> vector_int;
typedef vector<float> vector_float;

这些是我目前拥有的矢量包装器,它们可以工作,但我想知道是否有一种方法可以为所有矢量类型制作一个包装器。它必须进入 Extern C..所以它不能是模板。但我不想使用下面的包装器,我只想制作一个包装器,它可以传递给一个期望 vector_float*(typedeffor vector&lt;float&gt;) 或 vector_KeyPoint*(typedef for vector&lt;KeyPoint&gt;) 的函数或vector_int*(typedef for vector&lt;int&gt;) 等。我知道模板类,但我不能在这里使用它们,因为它必须进入extern C

vector_float* std_create_vectorf() 
    return new vector<float>;

vector_int* std_create_vector() 
    return new vector<int>;


vector_char* std_create_vectorc() 
    return new vector<char>;

这是我理想化的包装如果有人可以帮助我弄清楚如何实现这一点,我将不胜感激

vector_any_vec* std_create_vectorany() 
    return new vector<anyvector>;

【问题讨论】:

你要找的基本上是一个没有使用模板类的模板类。我真的不认为这是可能的。至少你最终会返回一个void*,这被认为是一个非常糟糕的主意。 @computerfreaker 感谢您回复我...你真的擅长 c++/c,我已经搜索了几次这个答案,但没有答案...如果我知道你是知识渊博,可能有助于给我指明方向……比如接受并继续前进等 我不是最擅长 C++,不,尤其是在模板类等更高级的东西方面。但是按照我看待您的问题的方式,您需要一个能够返回几乎任何数据类型的向量的函数。这意味着两件事之一:模板类(仍然需要一定程度的专业化)或void* 返回。模板类使用起来更干净、更安全,但您的extern "C" req 使这成为不可能。从技术上讲,您可以将 void* 返回到适当类型的向量,但我不确定您如何告诉您的函数使用什么类型来制作 vector 【参考方案1】:

如何使用运行时多态性将其封装在一个接口中?你牺牲了一点类型安全,但它应该能满足你的需要。

enum stored_type

    st_int,
    st_float,
    st_char
;

struct IGeneralVector

    virtual stored_type get_type() = 0;
    virtual void* get_data() = 0;
    virtual ~IGeneralVector();
;

class VectorFloatHolder : public IGeneralVector

    std::vector<float>* data;
public:
    VectorFloatHolder(std::vector<float>* in) : data(in)
    
    virtual stored_type get_type() override
    
        return st_float;
    
    virtual void* get_data() override
    
        return reinterpret_cast<void *>(data);
    

    virtual ~VectorFloatHolder()
    
        delete data;
    
;

IGeneralVector* std_create_vectorf()

    return new VectorFloatHolder(new std::vector<float>);

更新

阅读您的评论后,我对您想要实现的目标有了更好的了解。但是我不确定是否可以完全按照您的意愿去做,因为我不确定您有任何其他实现限制。这次是另一种使用类型擦除的方法。

class ObjectHolder

    struct base_type
    
        virtual ~base_type() 
    ;

    template<typename T>
    struct object_type : base_type
    
        object_type(const T& t) : object(t) 
        T object;
    ;

    std::unique_ptr<base_type> data;
public:
    template<typename T>
    VectorHolder(T t) : data(new object_type<T>(t))
    
    

    template<typename T>
    T GetData()
    
        object_type<T>* val = static_cast<object_type<T>*>(data.get());
        return val->object;
    
;

template<typename T>
ObjectHolder* std_create_vector()

    return new VectorHolder(new std::vector<T>);



int main()

    ObjectHolder* vh = std_create_vector < std::vector<float>>();
    // then later on you can get back the original type via:
    std::vector<float>* fp = vh->GetData<std::vector<float>*>();

【讨论】:

...感谢您的回答。我很感激。但是我在函数调用中注意到它是IGeneralVector* std_create_vectorf()...对于所有向量类型来说,这似乎仍然不是 1 个函数。它看起来就像一个浮点数。我在这里错过了什么吗?我只是希望有一个功能...一个我也许可以给int type 类型的 agrument 或键入它作为它正在使用...虽然我更喜欢前者...不过谢谢,如果我是不清楚,但您知道解决方案吗? 你知道吗,我非常感谢你到目前为止所花的时间。不过,我在帖子中确实提到了一件小事,它必须放在 Extern C 中……所以它不能是模板。 .你太好了,我不想把你赶出去,但你有解决这个问题的办法吗?这真的会回答很多?对我来说:)?

以上是关于我可以为任何可以放入 Extern C 的 C++ 向量制作一个 C 包装器吗的主要内容,如果未能解决你的问题,请参考以下文章

将 C++ 'extern "C" __declspec(dllexport)' 结构转换为 Rust 的问题

您可以在 C++ 中将指针声明为 extern 吗?

extern “C”的使用

等于c#中的c++ extern

C++编译过的C代码为什么要用extern C

c++面试常见300问