我目前正在使用C ++开发一个库(主要是因为从属库具有C ++接口)。我创建了带有C ++接口的概念验证实现,以实现快速开发。该库必须强制为其提供C接口。 C ++接口很好,但如果妨碍了C接口,则可以对其进行修改/删除。
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 ¶ms) = 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接口:
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接口的实现
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
}
我对此有一些疑问:
答案 0 :(得分:1)
我建议从C MyClass_GetResult方法返回Result *,例如int MyClass_GetResult(MyClassHandle handle, Result_C **result)
或Result_C* MyClass_GetResult(MyClassHandle handle)
。然后,为组和对象添加访问器。
由您决定,但我希望使用其中一个,但不能同时使用。
首先,我建议您决定要使用哪种语言及其功能(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