gpt4 book ai didi

c++ - 基于 OO 的 C++ 库的 C 和 C++ 接口(interface)

转载 作者:塔克拉玛干 更新时间:2023-11-03 00:46:30 24 4
gpt4 key购买 nike

我目前正在用 C++ 开发一个库(主要是因为依赖库有 C++ 接口(interface))。我使用 C++ 接口(interface)创建了一个概念验证实现,以便快速开发。库必须强制为其提供 C 接口(interface)。 C++ 接口(interface)很好,但如果它妨碍了 C 接口(interface),则可以修改/删除。

C++ API 现在看起来像这样:

typedef struct {
// only basic C data types like int,float.
int a;
float b;
} Object;

typedef struct {
std::vector<Object> objects;
} GroupOfObjects;

typedef struct {
std::vector<GroupOfObjects> groups;
} Result;

typedef struct {
// some basic C data types
int init1;
int init2;
float init3;
// some C++ types which I can possibly replace with something compatible with C
std::string init4;
std::vector<std::string> init5;
} MyClassInitParams;

struct IMyClass {
public:
virtual bool initialize(MyClassInitParams &params) = 0;
virtual bool getResult(Result &result) = 0;
//Other public methods, constructor, virtual destructor
}

// Actual implementation of the above interface
class MyClass : IMyClass {
}

IMyClass *createMyClassInstance();

到目前为止,我已经想出了这个 C 接口(interface):

extern "C" {

typedef struct MyClass *MyClassHandle;

// A C version of the above MyClassInitParams
typedef struct{

} MyClassInitParams_C;

typedef struct {
Object * objects;
int numObjects;
} GroupOfObjects_C;

// A C version of the above Result structure
typedef struct{
GroupOfObjects_C *groups;
int numGroups;
}Result_C;

MyClassHandle MyClass_Create();

MyClass_Destroy(MyClassHandle handle);

int MyClass_Initialize(MyClassHandle handle, MyClassInitParams_C *params);

int MyClass_GetResult(MyClassHandle handle , Result_C *result);

void MyClass_FreeResult(Result_C *result);

} // end of extern "C"

C接口(interface)的实现:

MyClassHandle MyClass_Create()
{
return createMyClassInstance();
}

MyClass_Destroy(MyClassHandle handle)
{
delete handle;
}

int MyClass_Initialize(MyClassHandle handle, MyClassInitParams_C *params)
{
MyClassInitParam params_cpp;
// fill params_cpp using the params structure

return handle->initialize (params_cpp);
}

int MyClass_GetResult(MyClassHandle handle , Result_C *result)
{
Result result_cpp;
bool ret = handle->getResult(result_cpp);

if (!ret)
return 0;

// Fill the C structure using the cpp structure
result->numGroups = result_cpp.groups.size();
result->groups = new GroupOfObjects_C[result->numGroups];
for (int i = 0; i < result->numGroups; i++) {
result->groups[i].numObjects = result_cpp.groups[i].objects.size();
result->groups[i].objects = new Object[result->groups[i].numObjects];
for (int j = 0; j < result->groups[i].numObjects; j++) {
result->groups[i].objects[j] = result_cpp.groups[i].objects[j];
}
}

return 1;
}

void MyClass_FreeResult(Result_C *result) {
// free all the arrays allocated in the above function
}

我有几个问题:

  1. GetResult 方法具有将对象从 C++ vector 复制到 C 数组的开销。有没有更优雅、更有效的方式来处理这个问题?
  2. 我将不得不维护 C 和 C++ 的结构。我应该只在 C++ 接口(interface)中使用 MyClassInitParams 和 Result 结构的 C 版本吗?这也有助于 (1)。
  3. 如果我使用 (2) 中的解决方案,甚至拥有 C++ 接口(interface)是否有意义?或者在这种情况下同时保留 C 和 C++ 接口(interface)有什么好处吗?

最佳答案

  1. 我建议从 C MyClass_GetResult 方法返回 Result*,例如 int MyClass_GetResult(MyClassHandle handle, Result_C **result)Result_C* MyClass_GetResult(MyClassHandle handle)。然后,为组和对象添加访问器。

  2. 由您决定,但我宁愿使用其中之一,但不能同时使用两者。

  3. 首先,我建议您确定要使用哪种语言及其功能(C 或 C++)来实现您的业务逻辑。接下来,另一种语言只不过是对用另一种语言实现的逻辑的包装。同样,如果您使用函数来访问实际的底层数据,您将摆脱复制此数据的麻烦,就像您在 MyClass_GetResult 方法中所做的那样。

举个例子

struct Object {
int a;
float b;
};

struct GroupOfObjects;
struct Result;
struct MyClass;

#ifdef __cplusplus

#include <vector>
struct GroupOfObjects {
std::vector<Object> objects;
};

struct Result {
std::vector<GroupOfObjects> groups;
};

struct MyClass {
private:
public:
Result getResult() { /*...*/ }
MyClass(int init1, int init2, float init3, const std::string& init4, const std::vector<std::string>& init5);
}

#endif

#ifdef __cplusplus
extern "C" {
#endif __cplusplus

struct Object* GroupOfObjects_GetObject(struct GroupOfObjects* g, size_t i)
/* { return &g.objects[i]; } */ // commented sections must be in cpp file, not in this header
size_t GroupOfObjects_GetCount(struct GroupOfObjects* g)
/* { return g.objects.size(); } */

struct GroupOfObjects* Result_GetGroup(struct Result* r, size_t i)
/* { return &r.groups[i]; } */
size_t Result_GetGroupCount(struct Result* r)
/* { return g.groups.size(); } */

MyClass *CreateMyClassInstance(int init1, int init2, float init3, const char* init4, const char** init5)
/* {
try {
std::vector<std::string> init5_v;
while (init5 != nullptr)
init5_v.push_back(std::string(*init5++));
return new MyClass(init1, init2, init3, std::string(init4), init5_v);
}
catch (...) {
return nullptr;
}
} */

void FreeMyClassInstance(struct MyClass* mc)
/* { delete mc; } */

Result* MyClass_GetResult(struct MyClass* mc)
/* {
Result *result = nullptr;
try {
result = new Result;
*result = mc->GetResult();
return result;
}
catch (...) {
delete result;
return nullptr;
}
} */

void FreeResult(struct Result* r)
/* { delete r; } */

#ifdef __cplusplus
} // end of extern "C"
#endif

关于c++ - 基于 OO 的 C++ 库的 C 和 C++ 接口(interface),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54079687/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com