c++ - 从 C 代码调用 C++ 函数

标签 c++ c function-calls

所以我看了herehere在第一个问题中提到的其他几个链接中,我已经有了以下代码:

.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++ 函数,您需要做两件事。 1) 让 C++ 代码知道它将被 C 使用,以便它可以生成 C 友好的符号。 2) 隐藏 C 无法理解的任何功能。

第一部分很容易实现,只需像在 C 中那样定义函数(即不使用任何仅 C++ 的功能,如 namespace ),然后如果定义了 C++,则将它们包装在 extern "C" block 中。您基本上希望您的头文件包含纯 C 代码,然后只需打开顶部的 extern block ,并在文件底部关闭它(我的示例将使这一点更清楚)。

第二部分有点棘手,但并不难。在你的例子中,你的函数返回一个 std::string ,它是一个 C++ 类。它不能在 C 中使用,因此要么需要用可以在 C 中使用的东西替换,要么需要隐藏在 C 可以使用的东西后面。为了争论起见,我们假设您不能用 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 的示例来向您展示如何操作。

注意我没有编译或测试这段代码,为了简单起见,我没有包含任何相关的头文件等。不过,它应该足以让您入门。

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

关于c++ - 从 C 代码调用 C++ 函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17739999/

相关文章:

Perl 函数参数消失。为什么?

c++ - 递归 boost::variant 类型不能用 "-std=c++11 -stdlib=libc++"编译

c++ - 为什么 fgetc() 读取非 ASCII 字符? (尝试加载 GLSL 着色器)

c++ - 使用 physfs 从 zip 内部使用 Lua "require"

c - 在STM32上调用memset时出现硬故障异常

c++ - 如何区分函数的声明和使用?

c++ - 在 C++ 中使用 enable_shared_from_this 时检查现有的 shared_ptr?

c++ - 如何在阅读时获取套接字流的位置

c - 如何避免在可移植上下文中按 Enter 清空输入缓冲区?

python - python 函数中的变量是否会在每次函数调用时重新初始化?