Search code examples
cgccc++17g++

how to include C++ library and header in vanilla C code


I am trying to call C++ library (on Bessel functions) inside C code. However, I am not sure how to include cmath into math.h. Most examples are on how to include C code into C++, but I am trying to do the reverse. Here is the C++ code that appears to work:

#include <cmath>
#include <iostream>
 
int main()
{
    // spot check for nu == 0
    const double x = 1.2345;
    std::cout << "I_0(" << x << ") = " << std::cyl_bessel_i(0, x) << '\n';
 
    // series expansion for I_0
    double fct = 1;
    double sum = 0;
    for (int k = 0; k < 5; fct *= ++k)
    {
        sum += std::pow(x / 2, 2 * k) / std::pow(fct, 2);
        std::cout << "sum = " << sum << '\n';
    }
}

How do I do this in (pure) C?


Solution

  • I am trying to call C++ library (on Bessel functions) inside C code.

    Generally speaking, you cannot call C++ standard library functions directly from C code unless they are also C standard library functions. Others, typically are not C functions at all. std::cyl_bessel_i() in particular, being overloaded, cannot itself be available as a C function.

    I am not sure how to include cmath into math.h. The latter already declares all the C functions in the standard math library. The former is the C++ version of the latter, with C++-specific additions.

    In practice, you might be able to make it work for your particular C and C++ implementations by figuring out details of name mangling and explicitly linking the C++ standard library to your C program. But a safer, easier, and more portable way to do it would be to write a thin wrapper with C linkage. Something like this:

    cyl_bessel_wrap.cpp

    #include <cmath>
    #include "cyl_bessel_wrap.h"
    
    extern "C" double cyl_bessel_i(double nu, double x) {
        return std::cyl_bessel_i(nu, x);
    }
    

    cyl_bessel_wrap.h

    #ifdef __cplusplus
    extern "C"
    #endif
    double cyl_bessel_i(double nu, double x);
    

    Your main.c then looks like this:

    #include <math.h>
    #include <stdio.h>
    #include "cyl_bessel_wrap.h"
     
    int main() {
        // spot check for nu == 0
        const double x = 1.2345;
        printf("I_0(%f) = %f\n", x, cyl_bessel_i(0, x));
     
        // series expansion for I_0
        double fct = 1;
        double sum = 0;
        for (int k = 0; k < 5; fct *= ++k) {
            sum += pow(x / 2, 2 * k) / (fct * fct);
            printf("sum = %f\n", sum);
        }
    }