Monday, February 5, 2024

[SOLVED] how to include C++ library and header in vanilla C code

Issue

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


Answered By - John Bollinger
Answer Checked By - Dawn Plyler (WPSolving Volunteer)