正常
static int torch_Tensor_(elementSize)(lua_State *L)
意味着torch_Tensor_ 是一个函数,它接受一个名为elementSize 的没有类型的参数(?!- 语法错误)并返回一个函数,该函数接受一个指向lua_State 的指针并返回一个int。这是公然无效的(函数不能返回其他函数)。
但这里实际发生的是 torch_Tensor_ 被定义为类似函数的宏,所以在编译器甚至看到这个声明之前,torch_Tensor_(elementSize) 就被其他东西替换了。
在https://github.com/torch/torch7/blob/master/Tensor.c有
#include "general.h"
#define torch_Storage_(NAME) TH_CONCAT_4(torch_,Real,Storage_,NAME)
#define torch_Storage TH_CONCAT_STRING_3(torch.,Real,Storage)
#define torch_Tensor_(NAME) TH_CONCAT_4(torch_,Real,Tensor_,NAME)
#define torch_Tensor TH_CONCAT_STRING_3(torch.,Real,Tensor)
#include "generic/Tensor.c"
#include "THGenerateAllTypes.h"
#include "generic/Tensor.c"
#include "THGenerateHalfType.h"
在lib/TH/THGeneral.h.in 中定义TH_CONCAT_...:
#define TH_CONCAT_STRING_3(x,y,z) TH_CONCAT_STRING_3_EXPAND(x,y,z)
#define TH_CONCAT_STRING_3_EXPAND(x,y,z) #x #y #z
#define TH_CONCAT_4_EXPAND(x,y,z,w) x ## y ## z ## w
#define TH_CONCAT_4(x,y,z,w) TH_CONCAT_4_EXPAND(x,y,z,w)
所以 torch_Tensor_ 在包含 generic/Tensor.c 之前被定义为宏。
torch_Tensor_(elementSize)
扩展到
TH_CONCAT_4(torch_,Real,Tensor_,elementSize)
扩展为
TH_CONCAT_4_EXPAND(torch_,...,Tensor_,elementSize)
... 是占位符,不是真正的代码。 Real在各种THGenerate*Type.h文件中被定义为宏,所以这一行实际上变成了
TH_CONCAT_4_EXPAND(torch_,char,Tensor_,elementSize)
TH_CONCAT_4_EXPAND(torch_,int,Tensor_,elementSize)
TH_CONCAT_4_EXPAND(torch_,float,Tensor_,elementSize)
...
取决于上下文。无论如何,最终结果是表单的单个标识符
torch_charTensor_elementSize
torch_intTensor_elementSize
torch_floatTensor_elementSize
...
(一个令牌)。
生成的函数定义因此看起来像例如
static int torch_charTensor_elementSize(lua_State *L)
{
...
}
取决于 generic/Tensor.c 包含在哪个上下文中。
这样做的原因是拥有相同的代码,但用于多种不同的类型。在 C++ 中,您将编写一个函数模板:
namespace torch {
template<typename Real>
static int Tensor_elementSize(lua_State *L) { ... }
}
但是 C 没有模板(也没有命名空间),因此获得像这样的“通用”代码的唯一方法是使用宏和预处理技巧手动完成(并手动“装饰”名称;例如 elementSize 函数floats 真的叫torch_floatTensor_elementSize)。
我们真正想做的只是对类型参数进行抽象,这里称为Real。