Единый файл заголовка для экспорта и API C и C++

У меня есть набор классов C++, объекты которых управляются в простом файле C++. Для этого файла у меня есть файл заголовка. К некоторым API-интерфейсам я хочу получить доступ из модуля C, а к некоторым из модуля C++. Любые предложения, как я могу этого добиться?

Чтобы опробовать этот подход, я написал следующие файлы.

Мой основной класс и его реализация (myclass.h и myclass.cpp):

myclass.h

#ifndef _MY_CLASS_H
#define _MY_CLASS_H

#include<iostream>
#include<string>

class MyClass
{
    public:
        MyClass();
        ~MyClass();

        void setServer(std::string url);
        void printServer();
    private:
        std::string serverURL;
};

#endif

myclass.cpp

#include "myclass.h"

MyClass::MyClass()
         :serverURL("")
{
}

MyClass::~MyClass()
{
}

void MyClass::setServer(std::string url)
{
    serverURL = url;
}

void MyClass::printServer()
{
    if (serverURL == "") {
        std::cout << "Server URL is empty\n";
    } else {
        std::cout << "Server URL : " << serverURL << std::endl;
    }
}

Теперь написана оболочка, использующая указанный выше класс. Цель состоит в том, чтобы предоставить два API init () и uninit () модулю C, а остальные два - модулю C++.

wrappe.h

#ifndef _WRAPPER_H
#define _WRAPPER_H

#include<string>

#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
// APIs that are exposed to C module(s)
void init();
void uninit();

#ifdef __cplusplus
}
#endif // __cplusplus

// C++ APIs exposed to C++ modules
#ifdef __cplusplus
void setServer(std::string url);
void printS();
#endif // __cplusplus

#endif // _WRAPPER_H

wrapper.cpp

#include "myclass.h"

static MyClass *myClass = 0;

void init()
{
    myClass = new MyClass();
}

void uninit()
{
    if (myClass != 0) {
        delete myClass;
    }
}

void setServer(std::string url)
{
    myClass->setServer(url);
}

void printS()
{
    if (myClass != 0) {
        myClass->printServer();
    }
}

Вот файлы модуля C, которые обращаются к API C.

backend.h

#ifndef _BACKEND_H
#define _BACKEND_H

#ifndef __cplusplus
extern "C" {
#endif

void backend_init();
void backend_uninit();

#ifndef __cplusplus
}
#endif

#endif

backend.c

#include "wrapper.h"
#include "backend.h"

void backend_init()
{
    init();
}

void backend_uninit()
{
    uninit();
}

Вот файлы модуля C++, которые вызывают API wrapper.h

guiuser.h

ifndef _GUIUSER_H
#define _GUIUSER_H

void gui1();
void gui2();

#endif

guiuser.cpp

#include "wrapper.h"

void gui1()
{
    setServer("localhost");
}

void gui2()
{
    printS();
}

Вот главный файл, который вызывает API модуля.

main.cpp

#include "guiuser.h"
#include "backend.h"
#include "wrapper.h"

int main()
{
    backend_init();
    gui1();
    gui2();
    backend_uninit();
}

Сбой компиляции для backend.c wrapper.h: 4: 17: фатальная ошибка: строка: нет такого файла или каталога компиляция прекращена.

Стоит ли разбивать wrapper.h на две части? Один для включения в бэкэнд и один для включения в guiuser?

Есть еще предложения по дизайну?

Присмотритесь к тому месту, где вы положили этот #include<string>.

molbdnilo 03.09.2018 08:18

компилятор gcc или g ++?

Potato 03.09.2018 08:18

molbdnilo - Ваш намек был полезен, и Р. Саху предоставил точное решение ошибки. Кроме того, была еще одна ошибка в wrapper.cpp. Мне пришлось включить wrapper.h в wrapper.cpp. С этими двумя изменениями я смог успешно скомпилировать и связать программу.

Venkata Subbarao 03.09.2018 09:05
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
3
288
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

<string> - это заголовок только для C++. Окружите строку #include <string> той же логикой препроцессора, которую вы используете для setServer.

#ifdef __cplusplus
#include <string>
#endif

Другие вопросы по теме