fa7eme
fa7eme

Reputation: 83

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

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

Answers (2)

TSG
TSG

Reputation: 887

Theory

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.

enter image description here

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.

EDIT: Code example

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

Acorn
Acorn

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

Related Questions