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++...).
Related
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"))
I have an external library written in C++ such as
external.h
#ifndef OUTPUT_FROM_CPP_H
#define OUTPUT_FROM_CPP_H
#include <cstdint>
extern "C" uint8_t myCppFunction(uint8_t n);
#endif
external.cpp
#include "external.h"
uint8_t myCppFunction(uint8_t n)
{
return n;
}
Currently I have no choice but use this C++ library in my current C project. But my compiler is telling me
No such file or director #include <cstdint>
when used in my C project
main.c
#include "external.h"
int main()
{
int a = myCppFunction(2000);
return a;
}
I understand that this is because cstdint is a C++ standard library that I'm trying to use through my C file.
My questions are:
Is there a way I can manage to use this C++ library in my C project without modifying my libary ?
If no, what whould I have to do on the library side to make it possible ?
The c prefix in cstdint is because it's really a header file incorporated from C. The name in C is stdint.h.
You need to conditionally include the correct header by detecting the __cplusplus macro. You also need this macro to use the extern "C" part, as that's C++ specific:
#ifndef OUTPUT_FROM_CPP_H
#define OUTPUT_FROM_CPP_H
#ifdef __cplusplus
// Building with a C++ compiler
# include <cstdint>
extern "C" {
#else
// Building with a C compiler
# include <stdint.h>
#endif
uint8_t myCppFunction(uint8_t n);
#ifdef __cplusplus
} // Match extern "C"
#endif
#endif
You have to modify the library.
Replace <cstdint> with <stdint.h>. Normally the former is recommended, but only the latter exists in C.
You should also be getting errors on extern "C". That's solved by putting following right below the includes:
#ifdef __cplusplus
extern "C" {
#endif
With a matching section at the end of file:
#ifdef __cplusplus
}
#endif
Then extern "C" can be removed from individual functions.
Is there a way I can manage to use this C++ library in my C project without modifying my libary ?
Create a separate header that is portable with C and use that header when compiling with C compiler:
// external_portable_with_c.h
// rewrite by hand or generate from original external.h
// could be just sed 's/cstdint/stdint.h/; s/extern "C"//'
#include <stdint.h>
uint8_t myCppFunction(uint8_t n);
// c_source_file.c
#include "external_portable_with_c.h"
void func() {
myCppFunction(1);
}
If no, what whould I have to do on the library side to make it possible ?
Is answered by other answers. Protect the C++ parts with #ifdef __cplusplus.
Note that (some? all?) compilers require the main function to be compiled with C++ compiler for C++ and C to work together properly. https://isocpp.org/wiki/faq/mixing-c-and-cpp#overview-mixing-langs
If you don't want to modify the library header, create a new file, for example includes_for_cpp/cstdint with content
#include <stdint.h>
Add the directory includes_for_cpp to the include path of your C project. After that, #include <cstdint> should find your file.
I am trying to use the complex matrix operations of the armadillo library but my whole code base is in C. How can I make a wrapper for the existing cpp library.
I have gone through examples online and I am able to make the wrapper for my own cpp library but I am a bit confused regarding an existing library such as armadillo.
I have gone through the link Using Eigen in a C Project
Here I am confused with the Library implementation part
/* foo.cpp */
#include "foo.h"
#include <iostream>
extern "C" {
void foo(int arg) {
std::cout << arg << std::endl;
}
} /* extern "C" */
How am I supposed to change the library implementation of armadillo and include the wrapper headers to it?
Thanks
guys.
I am writing an iOS app in swift, and I need to call some C++ lib. So I've build a simple example on how to bridge between C++ and Swift, and test on an iTouch. I wrapped the C++ interface with extern C. But I can't read the file when I call C++ function. Here is the code.
When I click the button on the iOS device, it needs to call the myFun():
main.swift
#IBAction func button(sender: AnyObject) {
myFun()
}
myFun() is my C++ function, which just reads a local file("hi.c").
DlibFun.cpp
#include <stdlib.h>
#include <stdio.h>
#include <string>
#include "DlibFun.h"
#include <unistd.h>
void myFun(){
char* path = (char*)"/hi.c";
FILE* f = fopen(path, "r");
if(f != NULL){
printf("open it\n");
fclose (f);
}else{
printf("FAIL\n");
}
}
Wrapper the C++ code in C
DlibFun.h
#ifdef __cplusplus
extern "C" {
#endif
int myFun();
#ifdef __cplusplus
}
#endif
photo-Bridging-Header.h
#include "DlibFun.h"
The result is that every time it prints out "FAIL". And any one give me any hint? I have tried the different path, but none of them are correct. Is it possible that my path is wrong? or there is any thicky thing that I don't know?
File folder
As you said, the code in the question is a simple example. I don't think the problem you are asking about, namely the fact that "FAIL" is output, is related to the real difficulties of bridging between C++ and Swift. The C++ function is called correctly, but the file can't be opened, most likely because it isn't there or isn't readable. In fact, I reproduced your example in Xcode, and got the output "open it" as long as the file was available; otherwise it would be "FAIL," as in your case.
Because DlibFun.cpp includes DlibFun.h, where myFun() is declared extern "C", the C++ compiler will compile myFun() to have C linkage, meaning it can be called from C and Swift. When Swift sees myFun() through the bridging header, it just treats it as a C function and calls it as such.
In a real-world situation, myFun() would be implemented in some C++ library and compiled using a C++ compiler, giving it C++ linkage, so just creating a header in Xcode, declaring myFun() extern "C", and then including the header in the bridge won't help. The build will fail with a link error.
To call the C++ library function myFun() you can write a wrapper as follows:
///////////////////
// File DlibFunW.h:
#ifndef DlibFunW_h
#define DlibFunW_h
// Because this is a C file for use by Swift code, via
// the bridge header, we don't need #ifdef __cplusplus.
// And because myFunW() was marked extern "C" in our C++
// wrapper, it's just a C function callable from Swift.
void myFunW();
#endif /* DlibFunW_h */
////////////////////
// File DlibFun.cpp:
#include "DlibFun.h"
// This file is C++ because it calls myFun(), which is
// a function with C++ linkage.
// This code is visible only to the C++ compiler, so
// we don't need #ifdef __cplusplus
extern "C" void myFunW() { myFun(); }
Now we don't need extern "C" in DlibFun.h, since myFun() has C++ linkage, as a real-world C++ library function would. The bridging header is now just
#include "DlibFunW.h"
and Swift calls myFunW() instead of myFun().
Of course, this is a very simple example dealing only with the C vs. C++ linkage problem. A real-world C++ function would take parameters and return values, often of pointer, struct, and class types, and dealing with those is a completely different can of worms. Here on StackOverflow you'll find plenty of info on that. Some questions I'd recommend:
Swift converts C's uint64_t different than it uses its own UInt64 type
How do I get a specific bit from an Integer in Swift?
Converting inout values to UnsafeMutablePointer<Unmanaged<TYPE>?>
Is it possible to convert a Swift class into C void* pointer?
Can I mix Swift with C++? Like the Objective - C .mm files
Hope you find useful info there, all the best!
I would like to write a c++ wrapper for a C API. for this it is most convenient to just include the C-API header in my own header, but this also includes the header into the file of the outer system, that should not be exposed to the C-API.
capi.h
enum MyFlags {
MY_FLAG_A,
MY_FLAG_B,
};
void FOO_bar(int flags);
cppapi.hh
#include "capi.h"
enum class MyFlags {
A = MY_FLAG_A,
B = MY_FLAG_B
};
namespace foo {
void bar(MyFlags flags) {
FOO_bar((int)flags);
}
}
it is just to translate c naming convention into c++ language features. So when using the C++ variant of the language, I would like that the c_api is not available to my auto completion and therefore not accidently used.
Define a namespace detail in your projects namespace, and include the C header there.
If the C header does not define en extern "C"- block when included from C++, do one of these:
Wrap with an external extern "C" block and verify the C header is, if included thus, valid and equivalent C++. (Special attention to enum sizes and inline functions).
Make it valid and equivalent C++ using #ifdef __cplusplus.
Thus, all those C functions are hidden in the internal implementation-detail namespace, and won't bother anyone.
namespace foo {
namespace internal {
extern "C" {
#include "capi.h"
}
}
// Function alias
using bar = internal::FOO_bar;
// Type alias
using config_t = internal::FOO_config;
}
Selectively get those symbols you need into the FOO-namespace using using.
BTW: Your forwarder-function should really be inline!
You should be able to arrange things using
#ifdef __cplusplus
/* C++ code here, including #include*/
#else
/*C code*/
#endif