Elegantly Call C++ from C

Elegantly call C++ from C

EDIT: Based on discussion in the comment, I should point out that separating things into a C-compatible struct duck and a derived class Duck is probably unnecessary. You can probably safely shovel the implementation into struct duck and eliminate class Duck, thus obviating real(…). But I don't know C++ well enough (in particular, the way it interacts with the C universe) to offer a definitive answer on this.


There is no reason you can't simply link all your C and C++ code together into a single binary.

Interfacing to the C++ code requires that you wrap the C++ API in a C API. You can do this by declaring a bunch of functions inside extern "C" { ... } when compiling the C++ code, and without the extern declaration when compiling the C client code. E.g.:

#ifdef __cplusplus
extern "C" {
#endif

typedef struct duck duck;

duck* new_duck(int feet);
void delete_duck(duck* d);
void duck_quack(duck* d, float volume);

#ifdef __cplusplus
}
#endif

You can define the duck struct in your C++ source, and even inherit the real Duck class from it:

struct duck { };

class Duck : public duck {
public:
Duck(int feet);
~Duck();

void quack(float volume);
};

inline Duck* real(duck* d) { return static_cast<Duck*>(d); }

duck* new_duck(int feet) { return new Duck(feet); }
void delete_duck(duck* d) { delete real(d); }
void duck_quack(duck* d, float volume) { real(d)->quack(volume); }

How to call C++ function from C?

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);
}

Calling C++ functions from a C src

First, :: is not valid in C.

Second, including a header is equivalent to copy-pasting a .h file into your C file. Your header must be valid C. Here's some deeper insight:

How to call C++ function from C?

Elegantly call C++ from C

Though, my alternative advice is, compile your C as C++. There's a chance it would take minimal or no work to turn out as valid C++.

Call C++ functions containing STL data types from C

Compile the C file by itself with the C compiler:

gcc -c cfile.c

then link all the files with the C++ compiler:

g++ -o a.out main.o cfile.o mylib.o

Note that you must compile the file with the main function with the C++ compiler. Any other files can be compiled with either, though you need extern "C" declarations to be able to call C code from C++ or create C++ functions that can be called from C

How to solve ambiguous declarations elegantly in C++11?

The almost always auto idiom to the rescue.

I'm not sure what you intended T to be, since it is unclear in the code example. I used double because... why not.

int main() {
auto n = int{};
auto m1 = B<double>(A{n});
auto m2 = B<double>(A(n));
}

Disclaimer: about half the C++ developers I talk to in real life (at my job) absolutely despise almost always auto. I like it (but I've done a lot of C# with var, F#, and TypeScript, where that's business as usual; and C++ template code and lambda-with-auto), but there are many who are ardently anti auto. If you decide to use almost always auto in your own project, I strongly urge you to discuss with your co-workers and get team consensus before going down that path.

How to elegantly avoid condition is always true warning for this particular kind of for-loop?

If you don't want to wrap it in code, wrap the code using conditional compilation:

#if UPPER > 0
int i;
for(i = 0; i < UPPER; i++) {
/* foo */
}
#endif

The elegance stems from:

  • No dead code when UPPER is 0.
  • Completely portable to any C compiler since 1970-01-01
  • Easy to read and understand

Calling C function from Perl within embedded C application

XSUBs actually don't require there to be an external library. They merely provide the ability to call to a c function from perl space, and provide some convenience in mapping the calling conventions between C and Perl.

All you need to do is register XSUBs you compiled into the embedding application with the perl interpreter you're embedding.

#include "XSUB.h"

XS(XS_some_func);
XS(XS_some_func)
{
dXSARGS;
char *str_from_perl, *str_from_c;

/* get SV*s from the stack usign ST(x) and friends, do stuff to them */
str_from_perl = SvPV_nolen(ST(0));

/* do your c thing calling back to your application, or whatever */
str_from_c = some_c_func(str_from_perl);

/* pack up the c retval into an sv again and return it on the stack */
mXPUSHp(c_str);
XSRETURN(1);
}

/* register the above XSUB with the perl interpreter after creating it */
newXS("Some::Perl::function", XS_some_func, __FILE__);

When embedding perl, this sort of thing is usually done in the xs_init function you pass to parse_perl.

EXTERN_C void boot_DynaLoader (pTHX_ CV* cv);

static void
xs_init (pTHX)
{
newXS("Some::Perl::function", XS_some_func, __FILE__);
/* possibly also boot DynaLoader and friends. perlembed has more
* details on this, and ExtUtils::Embed helps as well. */
newXS("DynaLoader::boot_DynaLoader", boot_DynaLoader, file);
}

perl_parse(my_perl, xs_init, argc, my_argv, NULL);

After that you'll be able to call to the XSUB as Some::Perl::function from perl space, and that XSUB in turn is free to call back to your application in any way it wants to.

Wrapping a C lib with extern C except an internal C++ include

Note that extern C isn't legal C, so it must only be included hen compiling as C++.

The already_compiled_c++.h header probably contains a guard against multiple includes, so just include it first:

#ifndef LIB_H
#define LIB_H

# This include added so that it won't get marked extern "C" when included by lob_foo.h.
#include <already_compiled_c++.h>

#ifdef __cplusplus
extern "C" {
#endif

#include "lib_foo.h"
#include "lib_bar.h"
#include "lib_baz.h"

#ifdef __cplusplus
}
#endif

#endif

Note: You need to check if already_compiled_c++.h is conditionally included and add the corresponding conditionals.

Compiling multiple languages together and calling function from one language to other

  • For calling C from C++ you don't need anything special, since C++ was designed this way
  • You can call C from Python by using native extensions for this you should use ctypes or swig read more here. And here is example how to call Windows API from Python.
  • There is Java Native Interface for calling native C libraries from Java and vice verse read more here
  • It is also possible to call C++ from C If I remember correctly you need to use "extern C" declaration in your C++ code read here
  • It is possible to call C from JavaScript (for example native node modules)

In fact almost any language has possibility to call C libraries because of amount of C libraries and because those are easy to port from system to system. In fact many complex systems uses script language for so called glue code witch uses C libraries. Any way this is broad topic you should tell more about your problem so that we could help you. If you jest want to test concept I think the Python way is easiest.



Related Topics



Leave a reply



Submit