3

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?

  • Unless you also compile the library in C, the included header and the underlying definition won't match. Instead, change the interface to be only C-callable, or add a new header and functions that "wrap" the C++ code and is C-callable. – crashmstr Jul 17 '14 at 14:32
  • Why would you want to write it in two languages? You could either create a C library and write C++ bindings for it, or write a C++ library and write C bindings for it. Then link that library with your application and voilà. – maxdev Jul 17 '14 at 14:32
  • Exported functions and data types of DLLs should be in C styles. – Yuan Jul 17 '14 at 14:32

2 Answers2

2

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++.

dohashi
  • 1,771
  • 8
  • 12
0

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.

Community
  • 1
  • 1
Ashu Pachauri
  • 1,283
  • 10
  • 16
  • Thanks for your answer, but for my case I do not want the application to be aware about my usage for the shared memory it is not his concern. –  Jul 17 '14 at 15:08
  • yeah..that's right. For that, you need to implement wrapper functions to do that for you. For example, you will need to have wrapper functions that accept and return C data types rather than C++ data types. – Ashu Pachauri Jul 17 '14 at 15:39