所以我已经有一段时间了,因为我直接使用C.而且我正处于一个项目中,我正在使用C++编写API.无论如何,这些方法中的大多数都只是C,并且所有返回值都是C结构.除了一个.我需要返回一种方法vector<string>.现在这是我的问题.C++方法/库/可以从C调用吗?我问,因为我不知道使用API的人是否会用C或C++编写,我觉得我应该只返回C结构.这需要我回来char**,对吗?
如果没有,我希望这是有道理的:
tl; dr version - 如果返回C结构,我可以从C调用C++方法,如果是,那么最好(仅?)等效返回值为vector<string>- > char**?
更新:C++方法只是全局方法.它们中没有类或面向对象的东西.除了我的向量问题之外,C++特有的唯一的东西是一些stringstreams
不,C不能使用C中不可用的C++特性.但是,C代码可以间接使用C++代码.例如,您可以使用C++实现C函数,并且可以在接口中使用opaque类型以便签名使用void*,但实现使用C++类.
C中vector <string>的等价物可能更接近:
typedef const char* c_string_type;
typedef struct c_string_array {
c_string_type* c_strings;
int c_strings_count;
} c_string_array_t;
Run Code Online (Sandbox Code Playgroud)
对于不透明类型,您将拥有以下内容:
typedef void* c_string_array_t;
int c_string_array_length(c_string_array_t array);
const char* c_string_array_get(c_string_array_t array, int index);
Run Code Online (Sandbox Code Playgroud)
然后你可以秘密地(在C++实现中)将std :: vector*强制转换为void*.
只要给出C-visible函数名称(在ABI级别忽略原型等),您可以从技术上调用C中的任何内容.当然,如果C无法以预期的方式生成参数,则无法获得正确的结果.通常,显而易见的解决方案是将接口简化为C级.char **是最大的共同点的最佳选择vector<string>.不仅如此,如果你知道你打算用它做什么,可能更快(更清洁恕我直言).
关于C可见性:函数名称不能与任何其他C可见函数共享.如果你希望你的C++函数可以从C调用,这可能是原型的一个很好的例子:
extern "C" char **lots_of_strings();
Run Code Online (Sandbox Code Playgroud)
如果参数签名不同,C++将允许您重载只能从C++可见的函数,并允许它们与C版本共存:
vector<string> lots_of_strings(int);
extern "C" char **lots_of_strings();
Run Code Online (Sandbox Code Playgroud)
如果你想提供几种方法来调用它,适用于调用语言,你可以试试这个(忽略后期初始化的弊端,以及boolC 中存在的事实):
bool lots_of_strings(vector<string> &);
extern "C" int lots_of_strings(char ***);
Whatever lots_of_strings(SomeArrayType &);
Run Code Online (Sandbox Code Playgroud)
请记住,在每种情况下,C++都会选择与调用站点具有最佳匹配签名的定义,而C将采用它可以做的任何事情(它始终是具有匹配名称的单个函数).
你会发现通过#ifdef与宏结合从C隐藏C++主义是有用的__cplusplus.
见这个FAQ.基本上,你不能调用C++方法(成员函数),但如果用extern C声明它们就可以调用独立函数. char **这不是唯一的可能性,但它可能是最直接的.您可以返回动态分配的数组char *.您将不得不使用out参数来向调用者提供长度(您可以使用NULL终止它,但这可能并不理想).例如
char **get_string_list(size_t *len)
{
char **array;
size_t actual_len;
// ...
*len = actual_len;
array = (char **) malloc(sizeof(char *) * actual_len);
// ...
return array;
}
Run Code Online (Sandbox Code Playgroud)
你必须以某种方式释放记忆.提供函数或记录调用者应该如何执行它.如果动态分配,请不要忘记释放单个字符串.