включить файл заголовка, созданный на C ++, используя extern в программе c - PullRequest
0 голосов
/ 03 августа 2020

У меня есть класс на C ++, который я хочу сделать из него разделяемой библиотекой и использовать на C или других языках. это класс, из которого я хочу сделать библиотеку:

getinfo.h

#ifndef GETINFO_H
#define GETINFO_H
#include "info.h"

char* getMaximumSpeedCpu();
char* getCoreNumbers();
#endif

getinfo. cpp:

#include <iostream>
#include "getinfo.h"
using namespace Morsa::Prd::SMC::SL;
char* getMaximumSpeedCpu()
{
    info *inf = new info;
    std::string str = inf->maximumSpeedCpu();
    char* maxspeed = new char[str.length()+1];
    strcpy(maxspeed, str.c_str());
    free(inf);
    return maxspeed;
}
char* getCoreNumbers()
{
    info *inf = new info;
    std::string corenum = inf->coreNumbers();
    char* num = new char[corenum.length()+1];
    strcpy(num, corenum.c_str());
    free(inf);
    return num;
}

и это мой класс-оболочка (sm c .h):

#ifndef SMC_H
#define SMC_H
#include "getinfo.h"

#ifdef __cplusplus
extern "C"
{
#endif
//void smc_destroy(ctestsmc *a);
char* smc_getMaximumSpeedCpu();
char* smc_getCoreNumbers();

#ifdef __cplusplus
}

#endif
#endif // SMC_H

sm c. cpp:

#include "smc.h"

char *smc_getMaximumSpeedCpu()
{
   char* c = getMaximumSpeedCpu();
   return c;
}

char *smc_getCoreNumbers()
{
    char* c = getCoreNumbers();
    return c;
}

Я сделал общую библиотеку из sm c. cpp, теперь я хочу использовать свою библиотеку, например, в коде C.

Как мне это сделать без включения файла заголовка? Всякий раз, когда я включаю файл заголовка sm c, мой код C не знает библиотек, которые я использовал в getinfo.h, например fstream.
EDIT:
info.h:

#ifndef INFO_H
#define INFO_H
#include <stdlib.h>
#include <cstring>
#include <sys/statvfs.h>
#include <libssh/libssh.h>

class info
{
private:
    std::ifstream ifile;
    std::ofstream ofile;
    std::vector<std::string> lists;
    std::string str;
    ssh_session my_ssh_session ;

public:
    info();
    info(const void *ip, const char* pw, const void *hostName);
    ~info();
    std::string maximumSpeedCpu();
    std::string coreNumbers();
    const void* _hostName;
    const void* _ip;
    const char* _password;

инфо. cpp:

#include "info.h"
info::info(const void *ip, const char* pw, const void *hostName)
{
    int a;
    _ip = ip;
    _password = pw;
    _hostName = hostName;
    my_ssh_session = ssh_new();
}
info::info()
{
}
info::~info()
{
    ssh_disconnect(my_ssh_session);
    ssh_free(my_ssh_session);
}

std::string info::maximumSpeedCpu()
{
    //maximum speed of cpu
    getSSHState();
    std::string cpuSpeed;
    cpuSpeed = exec_ssh_command(my_ssh_session, "dmesg | grep 'MHz processor' | awk '{print $5}'" );
    return cpuSpeed;
}

std::string info::coreNumbers()
{
    //number of processors
    getSSHState();
    std::string coresNumber;
    coresNumber = exec_ssh_command(my_ssh_session, "cat /proc/cpuinfo | grep processor | wc -l");
    return coresNumber;
}

Ответы [ 2 ]

2 голосов
/ 03 августа 2020

Теория

Вы можете получить доступ только к функциям, написанным на C из мира C. Каждый раз при вызове кода C ++ из C вы должны go через функцию-оболочку, в вашем случае smc_* functions.

Теперь обратите внимание, что объявление функций-оболочки, который находится в файле заголовка оболочки smc.h, не обязательно включать getinfo.hpp. Это ключевая идея . Заголовок оболочки просто сообщает любой программе C, которая ее включает, тип аргументов и возвращаемые значения функций smc_*. Заголовок должен соответствовать C.

Например, см. Изображение ниже. Функции foo и bar объявлены в файле wrapper.h, который только включает другие заголовки C. Файл wrapper.cpp, который фактически реализует оболочку и использует другие материалы из мира C ++ (например, STL или другие классы), включает заголовки C ++, которые ему нужны.

В вашем случае smc.cpp будет включать getinfo.hpp, а не smc.h.

введите описание изображения здесь

Однако определения этих функций-оболочек должны знать типы функций C ++, которые они обертывают. Следовательно, smc.cpp будет включать getinfo.h. Кроме того, поскольку этот файл будет скомпилирован компилятором C ++, он будет понимать любые ссылки на C ++ STL во включенных заголовках.

EDIT: Пример кода

Предположим, я хочу обернуть class cppworld .

cppworld.hpp :

class cppworld {
public:
    cppworld();
    int one();
};

cppworld. cpp:

#include <iostream>
#include "cppworld.hpp"

cppworld::cppworld() {}

int cppworld::one() {
    return 1;
}

Я пишу оболочка с wrapper.h и wrapper.cpp.

wrapper.h :

#ifdef __cplusplus
extern "C"
{
#endif

int get_one();

#ifdef __cplusplus
}
#endif

wrapper. cpp:

#include "wrapper.h"
#include "cppworld.hpp"

int get_one() {
    cppworld obj = cppworld();

    return obj.one();
}

Я могу скомпилировать wrapper.cpp и cppworld.cpp в общую библиотеку. Затем, чтобы использовать библиотеку из C, я создаю программу C ниже.

cworld. c

#include <stdio.h>
#include "wrapper.h"

int main() {
    printf("Calling one() returns: %d\n", get_one());
}
1 голос
/ 03 августа 2020

Всякий раз, когда я включаю заголовочный файл sm c, мой C код не знает библиотек, которые я использовал в getinfo.h, например fstream.

Да, вам необходимо предоставить C объявления (не определение) необходимых вам функций, и эти объявления не могут использовать функции C ++ (напрямую).

Например, вы не можете указать C такие вещи, как ссылки, шаблоны или перегруженные функции. Вы также не можете напрямую использовать произвольные объекты класса, такие как std::string, но вы можете передавать их как непрозрачные указатели, поскольку для C они являются просто указателями.

Независимо от того, как вы это делаете, вам нужно C, чтобы увидеть только то, что выглядит C на поверхности.

...