从C调用C ++方法

时间:2010-08-04 06:24:09

标签: c++ c

因为我已经使用过C,所以已经有一段时间了。我正处于一个我正在使用C ++编写API的项目。无论如何,这些方法中的大多数都只是C,并且所有返回值都是C结构。除了一个。我需要一种方法来返回vector<string>。现在这是我的问题。 C ++方法/库/可以从C调用吗?我问,因为我不知道使用API​​的人是否会用C或C ++编写,我觉得我应该只返回C结构。这需要我返回char**,对吗?

我希望有意义,如果没有:

tl; dr version - 如果它返回C结构,我可以从C调用C ++方法,如果是,那么vector<string>的最佳(仅?)等效返回值 - &gt; char**

更新:C ++方法只是全局方法。它们中没有类或面向对象的东西。除了我的向量问题之外,C ++特有的唯一的东西是stringstreams

6 个答案:

答案 0 :(得分:6)

不,C不能使用C中不可用的C ++特性。但是,C代码可以间接使用C ++代码。例如,您可以使用C ++实现C函数,并且可以在接口中使用opaque类型,以便签名使用void*,但实现使用C ++类。

vector&lt; string&gt;的等价物在C中可能更接近:

 typedef const char* c_string_type;
 typedef struct c_string_array {
     c_string_type* c_strings;
     int c_strings_count;
  } c_string_array_t;

对于opaque类型,你会有以下几点:

 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);

然后你可以秘密地(在C ++实现中)将std :: vector *强制转换为void *。

答案 1 :(得分:6)

只要给出C-visible函数名称(在ABI级别忽略原型等),您就可以从技术上调用C中的任何内容。当然,如果C无法以预期的方式生成参数,则无法获得正确的结果。通常,显而易见的解决方案是将接口简化为C级。对于char **的最大公分母,vector<string>是一个很好的选择。不仅如此,如果你知道你打算用它做什么,可能更快(更清洁恕我直言)。

关于C可见性:函数名称不能与任何其他C可见函数共享。如果您希望C ++函数可以从C调用,这可能是原型的一个很好的例子:

extern "C" char **lots_of_strings();

如果参数签名不同,C ++将允许您使用仅从C ++可见的函数重载,并允许它们与C版本共存:

vector<string> lots_of_strings(int);
extern "C" char **lots_of_strings();

如果你想提供几种方法来调用它,适用于调用语言,你可以试试这个(忽略后期初始化的弊端,以及C中存在bool的事实):

bool lots_of_strings(vector<string> &);
extern "C" int lots_of_strings(char ***);
Whatever lots_of_strings(SomeArrayType &);

请记住,在每种情况下,C ++都会选择与调用站点具有最佳匹配签名的定义,而C将采用它可以做的任何事情(它总是具有匹配名称的单个函数)。

通过将#ifdef与宏__cplusplus相结合,您会发现从C隐藏C ++主义非常有用。

答案 2 :(得分:5)

this FAQ。基本上,你不能调用C ++方法(成员函数),但如果用extern C声明它们就可以调用独立函数。char **不是唯一的可能性,但它可能是最直接的。您可以返回动态分配的char *数组。您将不得不使用out参数来为调用者提供长度(您可以使用NULL终止它,但这可能并不理想)。 E.g。

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;
}

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

答案 3 :(得分:0)

我前段时间读了一些关于这个的内容,并且你可以使用c ++编译的C ++代码/结构。但是有一些关于静态初始化的东西,如果我理解正确,你应该用c ++编写你的main函数保证这个si完成了,C主要做不到。

答案 4 :(得分:0)

如果您打算为C和C ++提供相同的功能,我会尝试提供两个入口点,以便您可以相互适应。请注意,虽然您可以选择可以在C和C ++中使用的接口,但在大多数情况下,C接口将不适合C ++使用(使用char**可能是C的良好解决方案,但拥有用户将其转换回C ++类型并执行清理会使用户代码混乱),反之亦然。

答案 5 :(得分:0)

如果您有可能修改您正在调用的代码,我建议您更改函数,将向量返回到以下内容:


unsigned int MyFunction(char* buff, unsigned int numLines, unsigned int stride)

其中numLines是分配的字符串数量,stride是字符串的大小。这样你的函数就不需要分配任何你需要担心的内存了。这一切都由来电者处理。函数的返回值是使用的字符串数量。