Right way to initialize a static library (C++)? - c++

I have a static C library that I want to port to C++, in the C library I got some global variables that store some common data used by the functions for example:
// global variable in the C library
int global_number_of_cpu_cores;
init_global_vars()
{
global_number_of_cpu_cores = get_info();
}
void lib_function()
{
// use global_number_of_cpu_cores
}
when using the library, it must be first initialized by the init function but in C++, the object's constructors are executed before the main function, so I cannot code:
class class_lib
{
class_lib()
{
// use global_number_of_cpu_cores but this is uninitialized!
}
}
Also, you can initialize global variables with functions:
int program_var = lib_function(); // lib_function uses global_number_of_cpu_cores but this is unintialized!
what is a decent/elegant way to solve this when designing a C++ library?
how do well-designed C++ libraries like Boost, Qt, etc solve this? any idea?

What you can do - simply create a C wrapper interface for C++ I.e. something like following:
In header file, e.g. foo.h
#ifndef __FOO_H_INCLUDED__
#define __FOO_H_INCLUDED__
#ifdef __cplusplus
extern "C" {
#endif
void print_logical_cpus()
#ifdef __cplusplus
}
#endif / * extern "C" */
#endif / * __FOO_H_INCLUDED__ */
in the implementation file e.g. foo.cpp
#include "foo.h"
#include <cstdio>
#include <thread>
struct GlobalSettings {
GlobalSettings():
logical_cpus(std::thread::hardware_concurrency())
{}
std::size_t logical_cpus;
};
static GlobalSettings __gsettings;
extern "C" {
void print_logical_cpus()
{
std::printf("Logical cpus %z", __gsettings.logical_cpus);
}
}
If you still need to port on raw C, there are compiler specific tricks to run functions before and after main.
GCC uses attribute((constructor)) and attribute((destructor)))
MS VC++ uses __declspec(allocate(".CRT$XLC"))

Related

How to wrap c++ std::shared_ptr in wrapper headerfile so it can be called from c?

I'm writing a small Wrapper API so i can call some C++ code (classes/ functions) from C.
I got the problem, that one of my C++ functions is initialised in my wrapper header with a "shared_ptr".
ClassName *ClassName _new(std::shared_ptr<Lib::Instance> p_Instance);
So as you can see, the wrapper file is infested with C++ style. This is bad because the Wrapper file should be readable by C AND C++.
This is my Wrapper.h file:
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
typedef struct ClassName ClassName;
ClassName *ClassName_new(std::shared_ptr<Lib::Instance> p_Instance);
void ClassName_setValue(ClassName* t, double p_value);
void ClassName_delete(ClassName* t);
#ifdef __cplusplus
}
#endif /* __cplusplus */
and this is my Wrapper.cpp file:
#include "Wrapper.h"
#include "ClassName.h"
extern "C"{
ClassName* ClassName_new(std::shared_ptr<Lib::Instance> p_Instance){
return new ClassName(p_Instance);
}
void ClassName_setValue(ClassName* t, double p_value){
t->setValue(p_value);
}
void ClassName_delete(ClassName* t){
delete t;
}
}
And this is the part of my main .cpp file
Header:
class ClassName: public Lib::Util::Task {
public:
ClassName(std::shared_ptr<Lib::Instance> p_Instance);
virtual ~ClassName();
void setValue(double p_value);
...
.Cpp:
ClassName::ClassName(std::shared_ptr<Lib::Instance> p_Instance) ...
...
void ClassName::setValue(double p_value){
doSomething()
}
...
I'm not allowed to change my structure of the main c++ file where I am using the ClassName(std::shared_ptr<Lib::Instance> p_Instance);
Do you have any ideas how I can fix this problem?
Maybe writing a second Wrapper?
Edit:
Here is the error given by the Terminal:
Wrapper.h:21:45: error: expected ‘)’ before ‘:’ token
ClassName *ClassName_new(std::shared_ptr<Lib::Instance> p_Instance);
^
The function cannot be used in C, so you can use the pre-processor to remove the declaration just like you used with extern "C":
// Wrapper.h
#ifdef __cplusplus
ClassName *ClassName_new(std::shared_ptr<Lib::Instance> p_Instance);
#endif
Although, it this wrapper isn't supposed to be used in C++ by anything other than Wrapper.cpp, then moving the declaration into Wrapper.cpp might be a better option.
If you need a way of invoking ClassName_new from C, I would suggest steering away from shared pointer. But you could make it work with an opaque wrapper:
// Wrapper.h
struct opaque_wrapper* make_instance(void);
void release_instance(struct opaque_wrapper*);
ClassName *ClassName_new(struct opaque_wrapper*);
// Wrapper.cpp
struct opaque_wrapper {
std::shared_ptr<Lib::Instance> p_Instance;
};
opaque_wrapper* make_instance() {
return new opaque_wrapper{std::make_shared<Lib::Instance>()};
}
void release_instance(struct opaque_wrapper* instance) {
delete instance;
}
ClassName *ClassName_new(struct opaque_wrapper* instance) {
return ClassName_new(instance->p_Instance);
}
I would suggest embedding the reference counter into the object and use boost::intrusive_ptr with it. This way you can pass a plain pointer to C functions and those C functions can still manage the object's lifetime directly calling C-style addref/release on it.
You cannot use classes from C++ in C.
You can define function prototypes of C calling convention C functions, to be used from C++ with the following wrapper code around in the header file:
#ifdef __cplusplus
extern "C" {
#endif
/* put here C calling convention C functions */
#ifdef __cplusplus
};
#endif
and you'll get a definitions file that can be used either in C or in C++. __cplusplus is a macro defined by the c++ compiler when compiling C++ code, and it introduces the extern "C" { environment to support C functions. Those functions follow the C style calling conventions (you cannot overload them, you cannot use method definitions or define classes in there)

Call C++ function in my C program [duplicate]

I know this.
Calling C function from C++:
If my application was in C++ and I had to call functions from a library written in C. Then I would have used
//main.cpp
extern "C" void C_library_function(int x, int y);//prototype
C_library_function(2,4);// directly using it.
This wouldn't mangle the name C_library_function and linker would find the same name in its input *.lib files and problem is solved.
Calling C++ function from C???
But here I'm extending a large application which is written in C and I need to use a library which is written in C++. Name mangling of C++ is causing trouble here. Linker is complaining about the unresolved symbols. Well I cannot use C++ compiler over my C project because thats breaking lot of other stuff. What is the way out?
By the way I'm using MSVC
You need to create a C API for exposing the functionality of your C++ code. Basically, you will need to write C++ code that is declared extern "C" and that has a pure C API (not using classes, for example) that wraps the C++ library. Then you use the pure C wrapper library that you've created.
Your C API can optionally follow an object-oriented style, even though C is not object-oriented. Ex:
// *.h file
// ...
#ifdef __cplusplus
#define EXTERNC extern "C"
#else
#define EXTERNC
#endif
typedef void* mylibrary_mytype_t;
EXTERNC mylibrary_mytype_t mylibrary_mytype_init();
EXTERNC void mylibrary_mytype_destroy(mylibrary_mytype_t mytype);
EXTERNC void mylibrary_mytype_doit(mylibrary_mytype_t self, int param);
#undef EXTERNC
// ...
// *.cpp file
mylibrary_mytype_t mylibrary_mytype_init() {
return new MyType;
}
void mylibrary_mytype_destroy(mylibrary_mytype_t untyped_ptr) {
MyType* typed_ptr = static_cast<MyType*>(untyped_ptr);
delete typed_ptr;
}
void mylibrary_mytype_doit(mylibrary_mytype_t untyped_self, int param) {
MyType* typed_self = static_cast<MyType*>(untyped_self);
typed_self->doIt(param);
}
I would do it in the following way:
(If working with MSVC, ignore the GCC compilation commands)
Suppose that I have a C++ class named AAA, defined in files aaa.h, aaa.cpp, and that the class AAA has a method named sayHi(const char *name), that I want to enable for C code.
The C++ code of class AAA - Pure C++, I don't modify it:
aaa.h
#ifndef AAA_H
#define AAA_H
class AAA {
public:
AAA();
void sayHi(const char *name);
};
#endif
aaa.cpp
#include <iostream>
#include "aaa.h"
AAA::AAA() {
}
void AAA::sayHi(const char *name) {
std::cout << "Hi " << name << std::endl;
}
Compiling this class as regularly done for C++. This code "does not know" that it is going to be used by C code. Using the command:
g++ -fpic -shared aaa.cpp -o libaaa.so
Now, also in C++, creating a C connector:
Defining it in files aaa_c_connector.h, aaa_c_connector.cpp. This connector is going to define a C function, named AAA_sayHi(cosnt char *name), that will use an instance of AAA and will call its method:
aaa_c_connector.h
#ifndef AAA_C_CONNECTOR_H
#define AAA_C_CONNECTOR_H
#ifdef __cplusplus
extern "C" {
#endif
void AAA_sayHi(const char *name);
#ifdef __cplusplus
}
#endif
#endif
aaa_c_connector.cpp
#include <cstdlib>
#include "aaa_c_connector.h"
#include "aaa.h"
#ifdef __cplusplus
extern "C" {
#endif
// Inside this "extern C" block, I can implement functions in C++, which will externally
// appear as C functions (which means that the function IDs will be their names, unlike
// the regular C++ behavior, which allows defining multiple functions with the same name
// (overloading) and hence uses function signature hashing to enforce unique IDs),
static AAA *AAA_instance = NULL;
void lazyAAA() {
if (AAA_instance == NULL) {
AAA_instance = new AAA();
}
}
void AAA_sayHi(const char *name) {
lazyAAA();
AAA_instance->sayHi(name);
}
#ifdef __cplusplus
}
#endif
Compiling it, again, using a regular C++ compilation command:
g++ -fpic -shared aaa_c_connector.cpp -L. -laaa -o libaaa_c_connector.so
Now I have a shared library (libaaa_c_connector.so), that implements the C function AAA_sayHi(const char *name). I can now create a C main file and compile it all together:
main.c
#include "aaa_c_connector.h"
int main() {
AAA_sayHi("David");
AAA_sayHi("James");
return 0;
}
Compiling it using a C compilation command:
gcc main.c -L. -laaa_c_connector -o c_aaa
I will need to set LD_LIBRARY_PATH to contain $PWD, and if I run the executable ./c_aaa, I will get the output I expect:
Hi David
Hi James
EDIT:
On some linux distributions, -laaa and -lstdc++ may also be required for the last compilation command. Thanks to #AlaaM. for the attention
Assuming the C++ API is C-compatible (no classes, templates, etc.), you can wrap it in extern "C" { ... }, just as you did when going the other way.
If you want to expose objects and other cute C++ stuff, you'll have to write a wrapper API.
You will have to write a wrapper for C in C++ if you want to do this. C++ is backwards compatible, but C is not forwards compatible.
export your C++ functions as extern "C" (aka C style symbols), or use the .def file format to define undecorated export symbols for the C++ linker when it creates the C++ library, then the C linker should have no troubles reading it
#include <iostream>
//////////////
// C++ code //
//////////////
struct A
{
int i;
int j;
A() {i=1; j=2; std::cout << "class A created\n";}
void dump() {std::cout << "class A dumped: " << i << ":" << j << std::endl;}
~A() {std::cout << "class A destroyed\n";}
};
extern "C" {
// this is the C code interface to the class A
static void *createA (void)
{
// create a handle to the A class
return (void *)(new A);
}
static void dumpA (void *thisPtr)
{
// call A->dump ()
if (thisPtr != NULL) // I'm an anal retentive programmer
{
A *classPtr = static_cast<A *>(thisPtr);
classPtr->dump ();
}
}
static void *deleteA (void *thisPtr)
{
// destroy the A class
if (thisPtr != NULL)
{
delete (static_cast<A *>(thisPtr));
}
}
}
////////////////////////////////////
// this can be compiled as C code //
////////////////////////////////////
int main (int argc, char **argv)
{
void *handle = createA();
dumpA (handle);
deleteA (handle);
return 0;
}
You can prefix the function declaration with extern “C” keyword, e.g.
extern “C” int Mycppfunction()
{
// Code goes here
return 0;
}
For more examples you can search more on Google about “extern” keyword. You need to do few more things, but it's not difficult you'll get lots of examples from Google.

How not to pollute the global namespace with declarations of a C header?

I'm trying to wrap a C library in C++, to make it a modern, high level and idiomatic C++ library. What I want to do, is to make the C objects completely opaque and/or directly unavailable from the C++ code and wrap/replace them with higher-level alternatives.
The problem I'm facing with is simple: I want to include the C header only to the C++ source, so that the C++ header when included won't include the C header's declarations as well, that is, it won't pollute the global namespace.
But it looks like the correct separation of the header and source files does not allow me to do that. Here is a very much dummified version of my problem, the comments will tell you the rest:
my_header.h:
typedef enum
{
my_Consts_ALPHA = /* some special value */,
my_Consts_BETA = /* other special value */,
} my_Consts;
typedef struct
{
// members...
} my_Type;
void
my_Type_method(my_Type *const,
my_Enum);
my_header.hpp:
namespace my
{
enum class Consts; // <-- This header is missing the constant values of
// this enum, because its values are defined by
// the C header :(
class Type : public my_Type // <-- The super struct is coming from the
// C header, but I don't want to include
// that header here :(
{
public:
void
method(Consts constant);
};
}
my_source.cpp:
extern "C"
{
#include "my_header.h"
}
#include "my_header.hpp"
namespace my
{
enum class Consts
{
ALPHA = my_Consts_ALPHA,
BETA = my_Consts_BETA,
};
void
Type::method(Consts constant)
{
my_Type_method(static_cast<my_Type *const>(this),
static_cast<my_Consts>(constant));
}
}
So my questions are: am I missing something very obvious here? Is this even possible to achieve? Is there a trick that I'm not aware of?
In the comments of the question #AnalPhabet suggested sarcastically, that one should use #include of a C header inside a namespace. #n.m. confirmed, that it is actually a working solution, and now I tested it on my own setup, and fortunately it is working pretty fine.
(Although I have no idea, if this is implementation specific or not, but I tested on both g++ and clang++ and it is working.)
It does not solve the opaqueness problem, but at least it makes a bit harder to access to the raw C data directly as it is living in a separate namespace now, therefore the user can't accidentaly access, but willingly.
So, the my_header.hpp should look like this:
namespace my
{
extern "C"
{
#include "my_header.h"
}
enum class Consts
{
ALPHA = my_Consts_ALPHA,
BETA = my_Consts_BETA,
};
class Type : public my_Type
{
public:
void
method(Consts constant);
};
}
So wherever my_header.hpp is #include'd, the user can only access to the C values as follows:
my::my_Consts_ALPHA // The wrapped value is => my::Consts::ALPHA
my::my_Type // The wrapped value is => my::Type
my::my_Type_method(t,..) // The wrapped value is => t.method(..)
If the whole idea of writing high-level and idiomatic C++ wrapper is to bring safety, automatic memory management and convenient C++ types like std::sting, I would include C header into cpp file only.
Provide clean idiomatic C++ interface, and use C library only in the implementation.
Do not afraid to write a couple of utility functions that convert C data to C++ and back. If a C++ class should hold C-specific data, and it is not possible to replace it with C++ analog, use some type erasure technique to keep clean interface.
I wouldn't worry about performance due to such wrapping until I see it on top in a profiler log. In most cases it is not a bottleneck.
Again, splitting interface and implementation is usually a win.
UPDATE
Initially, I was thinking more about project specific C++ interface rather than universal C++ wrapper around C library.
Solution with extern "C" wrapped into a namespace looks correct to me (see §7.5 of C++11 standard). But, I've never seen this technique in the wild.
You can go further and add nested detail namespace to not pollute my namespace with C types. This trick is popular in header only libraries:
namespace my
{
namespace detail
{
extern "C"
{
#include "my_header.h"
}
}
enum class Consts
{
ALPHA = detail::my_Consts_ALPHA,
BETA = detail::my_Consts_BETA,
};
class Type : public detail::my_Type
{
public:
void
method(Consts constant);
};
}
Take into account that you can't make C functions completely opaque or wrap them to a single namespace when you link with static library. They have external linkage and know nothing about namespaces.
namespace A {
extern "C" void my_Type_method(my_Type *const, my_Enum);
}
namespace B {
extern "C" void my_Type_method(my_Type *const, my_Enum);
}
extern "C" void my_Type_method(my_Type *const, my_Enum);
Basically, all these declarations refer to the same C function. As C doesn't support namespaces and overloading, linker usually uses function names as unique identifiers (even argument types are ignored).
Anyway, this approach will help to avoid accidental access to C interface.
I'm not sure if it's language legal, but I think extern "C" is just there to unmangle functions, so as long as you keep them in the .cpp file you can get away with this.
This is a little profane, but it seems to work with gcc 4.3.5. It demonstrates that you can use C functions while also hiding them in a namespace.
I didn't bother with inheriting struct_t, but it should probably work. I have no idea if you can pull off the enum class.
foo.h
#ifndef foo_H
#define foo_H
typedef enum {
ALPHA,
BETA
} enum_t;
typedef struct
{
int i;
} struct_t;
void printit(struct_t print_me);
#endif // foo_H
foo.c
#include <stdio.h>
#include "foo.h"
void printit (struct_t print_me)
{
printf ("Hello World %d!\n", print_me.i);
}
bar.hpp
#ifndef bar_HPP
#define bar_HPP
namespace _foo {
// Don't need extern "C" since we're not using functions
#include "foo.h"
}
struct based_on_struct_t // : public _foo:struct_t // Do you really have to derive? It might be possible, but it's ugly
{
_foo::struct_t i;
double j;
based_on_struct_t (int _i, double _j) : j(_j) { i.i = _i; }
void print(void); // Gonna call printit, MUST be in .cpp
};
#endif // bar_HPP
bar.cpp
namespace _foo{
extern "C" {
#include "foo.h"
}
}
#include "bar.hpp"
#include <stdio.h>
void based_on_struct_t::print (void) {
// Call the old version...
printit(i);
// And do new crap
printf ("Goodbye World %d %f\n", i.i, j);
}
driver.cpp
#include "bar.hpp"
int main (void) {
based_on_struct_t B(10, .1);
B.print();
return 0;
}
Demo...
$ gcc foo.c -c -O3
$ g++ foo.o bar.cpp driver.cpp
$ ./a.out
Hello World 10!
Goodbye World 10 0.100000
$

Porting a C library to C++

I would like to know if this is the correct way to port a C library to C++; for this example I wrote a 2 line C header with a function and a typedef managing a pointer.
lib.h
#ifndef LIB_H
#define LIB_H
#include <math.h>
double foo(double a) { return (log(a)); }
typedef double (*PtoFoo)(double);
#endif // LIB_H
lib.hpp
#ifndef LIB_HPP
#define LIB_HPP
namespace lib {
extern "C" {
#include "lib.h"
}
}
#endif // LIB_HPP
and a little test in C++11
#include <iostream>
#include "lib.hpp"
#include <functional>
int main() {
// call to the function
std::cout << lib::foo(42354.343) << "\n";
// trying the pointer to function type
lib::PtoFoo ptr = lib::foo;
std::function<double(double)> f(ptr);
std::cout << f(342.4) << "\n";
return (0);
}
right now my attention is focused on pointers, function pointers and functions, but in general I would like to know if this is the correct way to port standard C code to C++ and using the new c++ interface with namespaces without possible backfires .
Yes, that is the correct way to do it.
Alternatively, you can use the __cplusplus preprocessor token to define the C++ interface in the same header file:
#ifdef __cplusplus
namespace lib {
extern "C" {
#endif
typedef ...
#ifdef __cplusplus
}
}
#endif
The advantage of this approach is that only a single header file is required.
As I commented, C++ is designed to be compatible with C, so just wrapping your C library headers with the appropriate extern "C" { and } /* end extern "C"*/; is enough.
However, you may want to design a C++ friendly interface to your library. This requires some thoughts, and some code (most of it in C++ specific header files). For instance, you may want to provide interfaces using C++ object, overloading, operator, and template facilities.
I can't help more, but look for examples at: libonion and its C++ bindings, GTKmm which is a large C++ binding to GTK (and companion libraries like Glib...), the C++ class interface to gmplib, or even the newest C++11 standard thread library (i.e. std::thread etc, etc...) which could be viewed as a clever C++ wrapping of pthreads ....
I believe that each library could have its own C++ wrapping... How to design that is up to you... (depends a lot on the wrapped library, your available time, and your fluency with C++...).

Referencing C functions in static library from C++

I have a static library of functions written in C. Let's say the header file is called myHeader.h and looks like:
#ifndef MYHEADER_H
#define MYHEADER_H
void function1();
void function2();
#endif
function1 and function2 aren't anything too special. Let's say they exist in a file called impl1.c which looks like:
#include "myHeader.h"
void function1() {
// code
}
void function2() {
// more code
}
All of the code mentioned so far is compiled into some static library called libMyLib.a. I'd rather not modify any of the code used to build this library. I also have a C++ header (cppHeader.h) that looks like:
#ifndef CPPHEADER_H
#define CPPHEADER_H
class CppClass {
private:
double attr1;
public:
void function3();
};
#endif
Then cppHeader.cpp looks like:
#include "cppHeader.h"
#include "myHeader.h"
// constructor
CppClass::CppClass(){}
void CppClass::function3() {
function1();
}
When I try to compile this, I get an error about an undefined reference to function1(). I believe that I've linked everything properly when compiling. I'm pretty rusty in my C++. I'm sure that I'm just doing something stupid. I hope that my simple example code illustrates the problem well enough.
Thanks in advance for any help!
The other solution (to the one suggested originally by Yann) is to surround your "C" header with:
#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
}
#endif
Which saves you from having to remember to do:
extern "C" {
#include "foo.h"
}
every place you use foo.h
Make sure to use:
extern "C" {
#include "myHeader.h"
}
Or else the C++ compiler will generate symbol names which are name-mangled.