Reputation:
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:
Is this a correct way to build a library that can be used in both C & C++?
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
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
Reputation: 1403
Let me answer your questions one by one:
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.
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