在 c 程序中使用 extern 包含一个用 c++ 构建的头文件

include a header file built in c++ using extern in c program

我在 C++ 中有一个 class,我想从中创建一个共享库并在 C 或其他语言中使用。这是我想从中创建一个库的 class:

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

这是我的包装纸 class (smc.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

smc.cpp:

#include "smc.h"

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

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

我从 smc.cpp 创建了一个共享库,现在我想在 C 代码中使用我的库。

如果不包含任何头文件,我应该怎么做?每当我包含 smc 的头文件时,我的 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;

info.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 }'" );
    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;
}

理论

您只能从 C 的世界访问用 C 编写的函数。无论何时从 C 调用 C++ 代码,您都必须通过包装函数,在您的例子中是 smc_* 个函数。

现在,请注意包装函数的 声明,它位于包装函数的 header 文件 smc.h 中,不需要包含 getinfo.hpp. 这是关键见解。包装器的 header 仅告诉包含它的任何 C 程序、参数类型和 smc_* 函数的 return 值。 header必须坚持C.

例如,请参见下图。函数 foobarwrapper.h 文件中声明,其中 包含其他 C header。 wrapper.cpp 文件实际实现了包装器,并使用了 C++ 世界的其他东西(如 STL 或其他 类),包括它需要的 C++ header。

在您的情况下,smc.cpp 将包括 getinfo.hpp,而不是 smc.h

但是,这些包装函数的定义 需要知道它所包装的 C++ 函数的类型。因此,smc.cpp 将包括 getinfo.h。此外,由于此文件将由 C++ 编译器编译,因此它将理解包含的 headers.

中对 C++ STL 的任何引用。

编辑:代码示例

假设我想包装 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.hwrapper.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.cppcppworld.cpp编译成一个共享库。 然后,为了使用 C 中的库,我在下面创建了 C 程序。

cworld.c

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

int main() {
    printf("Calling one() returns: %d\n", get_one());
}

Whenever I include header file of smc, my C code doesn't know libraries that I had used in getinfo.h, like fstream.

是的,你需要给C你需要的函数的声明(而不是定义),而那些声明不能(直接)使用C++特性。

例如,您不能为 C 提供诸如引用、模板或重载函数之类的东西。您也不能直接使用任意 class 对象,例如 std::string,但您可以将它们作为不透明指针传递,因为对于 C 它们只是指针。

无论你怎么做,你都需要C来看到表面上看起来是C函数的东西。