C++代码的C API接口:不包装直接传递不透明指针

问题描述 投票:0回答:1

我目前正在为一些 C++ 代码设计一个 C API 接口(这个库是预构建的)。

到目前为止,每当我需要传递一个对象时,我都会使用以下模式

public.h

struct Object;

error_code take_object( Object * object );

private.h

#include<memory>
#include "..."

struct Object {
    std::shared_ptr< InternalObject > mObject;
};

impl.cpp

#include "public.h"
#include "private.h"

error_code take_object( Object * object ){ /* ... */ };

*我从示例中省略了

extern "C"
等样板

这很好用,除了我通常每次都必须提供一个明确的析构函数。然而,这个析构函数实际上具有破坏对象包装器和底层 InternalObject 的语义含义(除非它也被另一个资源使用)

但是我也有结构如下的对象

struct InteralObjectExtra {
    /* ... */
}

struct InternalObject {
    InternalObjectExtra data;
}

我需要公开这两个结构,但是不应显式删除 InternalObjectExtra,因为它是 InternalObject 的一部分。

我在想以下解决方案

public.h

struct Object;

#ifdef EXTERNAL
struct ObjectExtra;
#endif

/* ... */

private.h

struct Object {
    std::shared_ptr< InternalObject > mObject;
};

#ifdef INTERNAL
using ObjectExtra = InteralObjectExtra;
#endif

impl.cpp(仅供参考)

ObjectExtra * get_extra( Object * object ){
    return &( object->mObject.data );
}

但我不知道这是否safe(C ABI 和东西),我会假设只有指向这些类/结构的指针被传递。

我能看到的替代方案是放弃所有类型并求助于

void *
(我想避免)。

问题

我原来的解决方案安全吗?

如果没有,除了

void *
或使 ObjectExtra 成为一个包装器结构外,还有其他更好的方法,然后需要销毁它吗?

编辑

InternalObjectExtra 并不总是纯结构,但可能是模板化类型,例如

std::vector< int >

因此,简单地在 public.h 中编写

struct InternalObjectExtra
不是这些类型的选项。

c++ c abi
1个回答
-1
投票

为了将来参考,我采用的解决方案:

为了支持任何类型,无论是否基于模板,公开一个前向声明的结构并在内部将其转换为正确的类型。

公众:

struct vector_int;

私人:

vector_int * do_nothing(vector_int * in_vector) {
    auto internal_vec = reinterpret_cast <std::vector<int> *>(in_vector);
    // ... actually use the vector, like internal_vec->push_back(1);

    return reinterpret_cast <vector_int *>(internal_vec);
    // internal_vec is already a pointer, its value is an address.
    // and we couldn't return &internal_vec, it's going out of scope so its address isn't useful
}

这类似于

void *
解决方案,但保留了键入信息。

只要有可能,我还是会使用更简单的解决方案,例如对于

std::vector<int>
vector.data()
更好。但是,上面描述的解决方案更通用,可以在没有一个类型的干净 C 模拟的情况下应用。

© www.soinside.com 2019 - 2024. All rights reserved.