Reputation: 83
I have a class in C++ which I want to make a shared library from it and use in C or other languages. this is the class that I want to make a library from it:
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;
}
and this is my wrapper 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;
}
I made a shared library from smc.cpp, now I want to use my library in for example a C code.
How am I supposed to do it without including any header file? Whenever I include header file of smc, my C code doesn't know libraries that I had used in getinfo.h, like 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 $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;
}
Upvotes: 0
Views: 220
Reputation: 887
You can only access functions written in C from the world of C. Whenever calling C++ code from C, you must go through a wrapper function, in your case smc_*
functions.
Now, note that the declaration of the wrapper functions, which is in the wrapper's header file smc.h
does not need to include getinfo.hpp
. This is the key insight. The wrapper's header merely tells any C program that includes it, the type of arguments and return values of the smc_*
functions. The header must stick to C.
For example, see the image below. The functions foo
and bar
are declared in the wrapper.h
file which only includes other C headers. The wrapper.cpp
file which actually implements the wrapper, and uses other stuff from the C++ world (like the STL, or other classes) includes the C++ headers it needs.
In your case, smc.cpp
will include getinfo.hpp
, not smc.h
.
However, the definitions of these wrapper functions needs to know the types of the C++ functions it is wrapping. Therefore, smc.cpp
will include getinfo.h
. Further, because this file will be compiled by a C++ compiler, it will understand any references to C++ STL in included headers.
Suppose I want to wrap the class cppworld
.
cppworld.hpp:
class cppworld {
public:
cppworld();
int one();
};
cppworld.cpp:
#include <iostream>
#include "cppworld.hpp"
cppworld::cppworld() {}
int cppworld::one() {
return 1;
}
I write a wrapper with wrapper.h
and 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();
}
I can compile wrapper.cpp
and cppworld.cpp
into a shared library.
Then, to use the library from C, I create the C program below.
cworld.c
#include <stdio.h>
#include "wrapper.h"
int main() {
printf("Calling one() returns: %d\n", get_one());
}
Upvotes: 2
Reputation: 26066
Whenever I include header file of smc, my C code doesn't know libraries that I had used in getinfo.h, like fstream.
Yeah, you need to give C the declarations (not the definition) of the functions you need, and those declarations cannot use C++ features (directly).
For instance, you cannot give C things like references, templates or overloaded functions. You cannot directly use arbitrary class objects either, like an std::string
, but you can pass them around as opaque pointers since for C they are just pointers.
Regardless of how you do it, you need C to see only what appear to be C functions on the surface.
Upvotes: 1