Search code examples
c++ctemplateswrappername-mangling

Wrapper function for template<> in C++


I am currently trying to create a wrapper interface that can translate C++ to C, and while studying on the possibilities to do that, I came across the template functions (and classes). Knowing that these functions can take any data type and return any data type as well, I find it hard to create a corresponding caller function name that C could read. A simple example is the adder.

template <class typesToAdd>
typesToAdd addStuff(typesToAdd a, typesToAdd b) {
    return a + b;
}

My interface includes the extern "C" command to avoid the C++ name mangling in C.


Solution

  • You may use function templates to simplify both implementing and maintaining the actual code that does the work but to provide a C interface, you'll still need to explicitly instantiate the functions for the types you aim to support.

    If you'd like a C++ user to have the same restricted access to the functions as a C user will have, you can move the template implementation into the .cpp file and do the explicit instantiation there. A C++ user trying to use the function with types for which you have not explicitly instantiated the template will get a linking error.

    It could look something like this:

    // a.hpp
    #pragma once
    
    template <class T>
    T addStuff(const T& a, const T& b); // no implementation here.
    
    // a.cpp
    #include "a.hpp"
    #include "a.h"
    
    template <class T>
    T addStuff(const T& a, const T& b) {
        T rv = a;
        rv += b;
        return rv;
    }
    
    // C interface - note: it's inside the .cpp file
    extern "C" {
    
    int add_ints(int a, int b) {
        return addStuff(a, b);
    }
    
    double add_doubles(double a, double b) {
        return addStuff(a, b);
    }
    
    }
    
    /* a.h */
    #pragma once
    
    #ifdef __cplusplus
    extern "C" {
    #endif
    
    int add_ints(int, int);
    double add_doubles(double, double);
    
    #ifdef __cplusplus
    }
    #endif
    

    A C user can now include the .h file and call the two functions for which you've provided an implementation.

    Example:

    // main.c
    #include "a.h"
    
    #include <stdio.h>
    
    int main() {
        printf("%d\n", add_ints(10, 20));
        printf("%f\n", add_doubles(3., .14159));
    }
    

    Compilation:

    g++ -c a.cpp
    gcc -o main main.c a.o