user3849502
user3849502

Reputation:

Linking C program to C++ Shared Library

I have shared library written in C++ which provides some APIs calls for different applications written in C++ too, now I want to use this library inside C programs. The original library contained data-types that are only valid for C++ like std::string and std::vector as follow:

typedef u_int32_t           ApplicationID;
typedef std::string         IPAddress;
typedef std::vector<int>    SDLIST;

These data-types are being used as input parameters for the APIs:

register_client(IPAddress ip);
export(ApplicationID id, SDLIST *list);

But in C, we don't have string nor vector and these two data-types should be modified as follow:

typedef char*   IPAddress;
typedef int*    SDLIST;

I tried to do the following changes in my code:

typedef u_int32_t           ApplicationID;
enter code here
#ifdef __cplusplus
    typedef std::string         IPAddress;
    typedef std::vector<int>    SDLIST;
#else
    typedef char*               IPAddress;
    typedef int*                SDLIST;
#endif


#ifdef __cplusplus
extern "C" {
#endif

    register_client(IPAddress ip);
    export(ApplicationID id, SDLIST *list);

#ifdef __cplusplus
}
#endif

My questions are:

  1. Is this a correct way to build a library that can be used in both C & C++?

  2. My shared library use Boost Interprocess library which is a wrapper for the standard POSIX shared memory calls. Whenever I try to link this shared library to any application, I should include the lrt again in the application. So my question is it possible to link the shared library statically to the lrt library without having the need to include the lrt in all applications that use my shared library?

Upvotes: 3

Views: 545

Answers (2)

dohashi
dohashi

Reputation: 1841

If you want this to work you are going to need to build a C++ interface library that implements a C based API that converts the C datatypes into C++ datatypes. In particular a std::string is not a char * and vector is not int *.

For example if the API defines a C++ funciton like

bool CPPAPIFunction( std::string str, std::vector<int> vec )

you'll need to implement a wrapper function (compiled and link as C++) like

int myCMappingFunction( char *cstr, int *carray, int arraylen )
{
    std::string str( cstr );
    std::vector<int> vec;
    for (int i =0; i < arraylen; i++ )  // ... copy C array into C++ vector
    return (int)CPPFAPIFunction( str, vec );
}

Also don't forget to declare your wrapper function in a extern "C" block, so that the name mangling will be C style not C++.

Upvotes: 2

Ashu Pachauri
Ashu Pachauri

Reputation: 1403

Let me answer your questions one by one:

  1. Obviously, it is as per your use case what kind of code you want to mix. If you want to provide capability that your library should be callable from C and C++, your library interface should be C compatible. Look Using C++ library in C code for an answer to how to wrap your C++ functions in a C interface.

  2. It is generally advised that you do not pack your library with all your dependencies because it makes a heavy binary and defeats the purpose of shared libraries, unless the dependencies you are packing are small. However, in your case, if you want to do that, you need to create static shared library. However, it is not possible to create from two shared libraries. You need object files for both of them. See Merge multiple .so shared libraries for an answer.

Upvotes: 0

Related Questions