C ++中template <>的包装函数

问题描述

我目前正在尝试创建一个可以将C ++转换为C的包装器接口,并且在研究实现这种包装的可能性时,我遇到了模板函数(和类)。知道这些函数可以采用任何数据类型,也可以返回任何数据类型,因此我发现很难创建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