在 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.
例如,请参见下图。函数 foo
和 bar
在 wrapper.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.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());
}
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函数的东西。
我在 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.
例如,请参见下图。函数 foo
和 bar
在 wrapper.h
文件中声明,其中 仅 包含其他 C header。 wrapper.cpp
文件实际实现了包装器,并使用了 C++ 世界的其他东西(如 STL 或其他 类),包括它需要的 C++ header。
在您的情况下,smc.cpp
将包括 getinfo.hpp
,而不是 smc.h
。
但是,这些包装函数的定义 需要知道它所包装的 C++ 函数的类型。因此,smc.cpp
将包括 getinfo.h
。此外,由于此文件将由 C++ 编译器编译,因此它将理解包含的 headers.
编辑:代码示例
假设我想包装 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());
}
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函数的东西。