Чтобы вызвать функции C++ из C, вам нужно сделать две вещи. 1) Пусть код C++ знает, что он будет использоваться C, чтобы он мог генерировать C-дружественные символы. 2) Скрыть любую функциональность, которую C не может понять.
Первая часть легко достигается путем простого определения функций, как в C (I.E. не использовать какие-либо объекты на C++, такие как пространства имен), а затем их обертывание в блок extern «C», если определено C++. В основном вы хотите, чтобы ваш заголовочный файл содержал только C-код, а затем просто откройте блок extern вверху и закройте его в нижней части файла (мой пример сделает это более понятным).
Вторая часть немного сложнее, но не слишком сложна. В вашем случае ваша функция возвращает std :: string, которая является классом C++. Он не может использоваться в C и поэтому либо должен быть заменен чем-то, что можно использовать в C, либо его нужно скрывать за тем, что C может использовать. Для аргумента предположим, что вы не можете заменить std :: string на say, char *. В этом случае вам нужно скрыть std :: string из кода C-обрамления. Обычный способ сделать это - использовать opaque pointer.
В принципе, код C-обрамления имеет только указатель на что-то. Это то, о чем он не знает и не заботится. Код C++ может свободно использовать std :: string внутри, но должен обязательно скрыть его перед взаимодействием с C API. В моем примере вы можете видеть, что я предоставил непрозрачный указатель на структуру, которую я назвал cppstring.
В исходном файле cppstring - это просто структура, содержащая std :: string. Я изменил ваш примерный код, чтобы использовать новую структуру cppstring. Важно отметить, что, поскольку код C может обрабатывать только указатель на cppstring, нам нужно создать его в куче в нашем C++-коде и вернуть указатель на него. Это означает, что мы должны предоставить пользователям C некоторый способ освободить его, когда они будут сделаны, что я также представил в примере.
Используя эту технику, вы можете обернуть всю std :: string за API C, чтобы пользователи C могли использовать все функции, которые предоставляет std :: string. Я привел пример wrapping 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));
}
@MarkGarcia повторно редактировал вопрос & название по этому вопросу см в основном конец вопроса ... й основной 'Int основной (INT ARGC, символ ** ARGV) {}' – cxzp
Разве вы не должны верните C-строку вместо 'std :: string'? – nouney
Вы не можете. Тип результата exec не существует на C, вам, возможно, потребуется написать c-совместимую обертку в C++-части. – urzeit