从C代码调用C++函数
Calling C++ function from a C code
所以我看了这里和这里,以及第一个问题中提到的其他几个链接,我已经有了以下代码:
.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主函数int main(int argc, char** argv) {}
调用.cpp文件中的函数
第一部分很容易实现,只需像在C中那样定义函数(即不要使用任何仅限C++的功能,如名称空间),然后如果定义了C++,则将它们封装在外部"C"块中。您基本上希望您的头文件包含仅C代码,然后只需打开顶部的extern块,然后在文件底部关闭它(我的示例将使这一点更加清楚)。
第二部分有点棘手,但并不太难。在您的情况下,您的函数返回一个std::字符串,它是一个仅限C++的类。它不能在C中使用,因此要么需要用在C中可以使用的东西替换,要么需要隐藏在C可以使用的后面。为了便于讨论,我们假设您不能用char*替换std::string。在这种情况下,您需要从面向C的代码中隐藏std::string。执行此操作的常见方法是使用不透明指针。
基本上,面向C的代码只处理指向某个对象的指针。这是它既不知道也不关心的事情。C++代码可以在内部自由使用std::字符串,但必须确保在与C API接口之前将其隐藏。在我的例子中,您可以看到我提供了一个不透明的指针,指向一个我称为cppstring的结构。
在源文件中,cppstring只是一个包含std::字符串的结构。我已经将您的示例代码更改为使用新的cppstring结构。需要注意的一点是,因为C代码只能处理指向cppstring的指针,所以我们需要在C++代码的堆上创建它,并返回指向它的指针。这意味着我们必须为C用户提供一些在完成后释放它的方法,我在示例中也提供了这种方法。
使用这种技术,您可以将整个std::string封装在C API后面,允许C用户使用std::字符串提供的所有功能。我提供了一个包装std::string::substr的例子来向您展示如何包装。
注意:我没有编译或测试过这段代码,为了简单起见,我没有包含任何相关的头文件等。不过,这应该足以让你开始。
// 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));
}
您需要在cpp文件中将函数声明为extern"C":
extern "C" char *exec(char* cmd, FILE* pipe) {
...
}
在头/链接器文件中,您需要用关键字"extern"声明它的原型,如下所示:
extern char *exec(char* cmd, FILE* pipe);
此外,您确定要将c++的std::字符串返回到c代码中吗?
- "error: no matching function for call to"构造函数错误
- 什么时候调用组成单元对象的析构函数
- 继承函数的重载解析
- 为什么随机数生成器不在void函数中随机化数字,而在main函数中随机化
- C++模板来检查友元函数的存在
- 递归函数计算序列中的平方和(并输出过程)
- 对RValue对象调用的LValue ref限定成员函数
- C++17复制构造函数,在std::unordereded_map上进行深度复制
- 将数组作为参数传递给函数安全吗?作为第三方职能部门,可以探索他们想要的之外的其他元素
- 在C++STL中是否有Polyval(Matlab函数)等价物?
- 为什么使用 "this" 指针调用派生成员函数?
- 将对象数组的引用传递给函数
- 函数调用中参数的顺序重要吗
- 函数向量_指针有不同的原型,我可以构建一个吗
- 使用不带参数的函数访问结构元素
- 代码在main()中运行,但在函数中出现错误
- 内置函数可查看CPP中的成员变量
- 如何获取std::result_of函数的返回类型
- 如何在c++中为模板函数实例创建快捷方式
- 如果C++类在类方法中具有动态分配,但没有构造函数/析构函数或任何非静态成员,那么它仍然是POD类型吗