所以我看了here和here以及第一个问题中提到的其他几个链接,我已经有了以下代码:
.cpp文件:
#include "arp_piping.h"
#include <string>
#include <iostream>
#include <stdio.h>
std::string exec(char* cmd, FILE* pipe) {
pipe = _popen(cmd, "r");
if (!pipe) return "ERROR";
char buffer[128];
std::string result = "";
while(!feof(pipe)) {
if(fgets(buffer, 128, pipe) != NULL)
result += buffer;
}
_pclose(pipe);
return result;
}
标头/链接器文件:
#ifndef ARP_PIPING_H
#define ARP_PIPING_H
#endif
#ifdef __cplusplus
#define EXTERNC extern "C"
#else
#define EXTERNC
#endif
my function goes here something like
EXTERNC .....exec(char* cmd, FILE* pipe) ????
#undef EXTERNC
我的问题是上面的内容,因为我不确定要输入什么。我试图从我的C main函数int main(int argc, char** argv) {}
答案 0 :(得分:4)
要从C调用C ++函数,您需要做两件事。 1)让C ++代码知道它将被C使用,以便它可以生成C友好符号。 2)隐藏C无法理解的任何功能。
第一部分很容易通过简单地定义函数来实现,就像在C中一样(I.E.不使用任何C ++只有命名空间的特性),然后在定义C ++的情况下将它们包装在extern“C”块中。您基本上希望您的头文件包含仅C代码,然后只需打开顶部的extern块,然后将其关闭在文件的底部(我的示例将使其更清晰)。
第二部分有点棘手,但并不太难。在您的情况下,您的函数返回一个std :: string,它只是一个C ++类。它不能在C中使用,因此需要替换为可以在C中使用的东西,或者它需要隐藏在C可以使用的东西后面。为了论证,我们假设你不能用say,char *替换std :: string。在这种情况下,您需要从面向C的代码中隐藏std :: string。这样做的常用方法是使用opaque pointer。
基本上,面向C的代码只处理指向某事物的指针。这件事既不知道也不关心。 C ++代码可以在内部自由使用std :: string,但必须确保在与C API连接之前隐藏它。在我的例子中,你可以看到我提供了一个指向我称为cppstring的结构的不透明指针。
在源文件中,cppstring只是一个包含std :: string的结构。我已经更改了您的示例代码以使用新的cppstring结构。需要注意的一件重要事情是,因为C代码只能处理指向cppstring的指针,所以我们需要在C ++代码中的堆上创建它并返回指向它的指针。这意味着我们必须为C用户提供一些在完成时释放它的方法,我在示例中也提供了这些方法。
使用这种技术,您可以将整个std :: string包装在C API之后,允许C用户使用std :: string提供的所有功能。我提供了一个包装std :: string :: substr的例子来向你展示如何。
N.B。我没有编译或测试过这段代码,为了简单起见,我没有包含任何相关的头文件等。不过,它应该足以让你入门。
// C header
#ifdef __cplusplus
extern "C" {
#endif
typedef struct cppstring *cppstring_p;
cppstring_p exec(char *cmd, FILE *pipe);
void free_cppstring(cppstring_p cppstr);
/* example of wrapping std::string::substr for C users */
cppstring_p substr(cppstring_p str, int pos, int count);
#ifdef __cplusplus
}
#endif
// CPP source
struct cppstring {
std::string data;
cppstring(void) {}
cppstring(std::string const& s) : data(s) {}
};
cppstring_p exec(char *cmd, FILE *pipe) {
pipe = _popen(cmd, "r");
if (!pipe) return "ERROR";
char buffer[128];
auto result = new cppstring;
while(!feof(pipe)) {
if(fgets(buffer, 128, pipe) != NULL)
result->data += buffer;
}
_pclose(pipe);
return result;
}
void free_cppstring(cppstring_p cppstr) {
delete cppstr;
cppstr = nullptr;
}
cppstring_p substr(cppstring_p str, int pos, int count) {
assert(str);
return new cppstring(str->data.substr(pos, count));
}
答案 1 :(得分:3)
您需要在cpp文件中将该函数声明为extern“C”:
extern "C" char *exec(char* cmd, FILE* pipe) {
...
}
在标题/链接器文件中,您需要使用关键字“extern”声明它的原型,如下所示:
extern char *exec(char* cmd, FILE* pipe);
另外,你确定要将c ++的std :: string返回给你的C代码吗?