从C调用C++方法

Fal*_*rri 7 c c++

所以我已经有一段时间了,因为我直接使用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

Mic*_*yan 6

不,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*.


Mat*_*ner 6

只要给出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.


Mat*_*hen 5

这个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)

你必须以某种方式释放记忆.提供函数或记录调用者应该如何执行它.如果动态分配,请不要忘记释放单个字符串.

  • 不会.简单的情况可能会巧合地在某些编译器上工作(因为`new`通常用`malloc`实现),但这绝对是错误的. (8认同)