C++ 中模板 <> 的包装函数

Wrapper function for template<> in C++

我目前正在尝试创建一个可以将 C++ 转换为 C 的包装器接口,在研究这样做的可能性时,我遇到了模板函数(和 类)。知道这些函数可以采用任何数据类型和 return 任何数据类型,我发现很难创建 C 可以读取的相应调用函数名称。一个简单的例子就是加法器。

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

我的界面包含 extern "C" 命令以避免 C 中的 C++ 名称重整。

模板不是适用于任何数据类型的函数。它是在编译时创建的函数模板。您使用的每种类型都会在二进制文件中创建一个带有新符号的新函数。

要导出到 C,您必须从 C 中专门化您要使用的类型,例如:

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

extern "C" {

    int addStuffInt(int a, int b) {
        return addStuff(a, b);
    }

}

您可以使用函数模板来简化执行工作的实际代码的实现和维护,但要提供 C 接口,您仍然需要为您要支持的类型显式实例化函数。

如果您希望 C++ 用户对函数的访问权限与 C 用户相同,您可以将模板实现移到 .cpp 文件中并在那里进行显式实例化。尝试将函数与您尚未显式实例化模板的类型一起使用的 C++ 用户将收到链接错误。

它可能看起来像这样:

// 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

C 用户现在可以包含 .h 文件并调用您提供实现的两个函数。

示例:

// main.c
#include "a.h"

#include <stdio.h>

int main() {
    printf("%d\n", add_ints(10, 20));
    printf("%f\n", add_doubles(3., .14159));
}

编译:

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