簡體   English   中英

從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 ++函數,您需要做兩件事。 1)讓C ++代碼知道它將由C使用,以便它可以生成C友好符號。 2)隱藏C無法理解的任何功能。

通過像在C語言中那樣簡單地定義函數(IE不使用任何僅C ++特性,例如名稱空間),然后將它們包裝在外部“ C”塊(如果定義了C ++)中,就可以輕松實現第一部分。 基本上,您希望頭文件包含純C代碼,然后僅在頂部打開extern塊,然后在文件底部將其關閉(我的示例將使這一點更加清楚)。

第二部分有點棘手,但並不難。 在您的情況下,您的函數返回std :: string,這是僅C ++的類。 它不能在C語言中使用,因此需要用可以在C語言中使用的東西替換,或者需要將其隱藏在C語言可以使用的東西后面。 為了論證,我們假設您不能將std :: string替換為char *。 在這種情況下,您需要從面向C的代碼中隱藏std :: string。 常用的方法是使用不透明的指針

基本上,面向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));
}

您需要在cpp文件中將函數聲明為extern“ C”:

extern "C" char *exec(char* cmd, FILE* pipe) {
   ...
}

在頭文件/鏈接器文件中,您需要使用關鍵字“ extern”聲明其原型,如下所示:

extern char *exec(char* cmd, FILE* pipe);

另外,您確定要向C代碼返回c ++的std :: string嗎?

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM