当前正在查看一些对我没有任何意义的C代码。什么是(elementSize)?应该如何将参数传递给此静态函数?这种语法样式的名称是什么,以便我可以进一步了解它?
static int torch_Tensor_(elementSize)(lua_State *L)
{
luaT_pushinteger(L, THStorage_(elementSize)());
return 1;
}
https://github.com/torch/torch7/blob/master/generic/Tensor.c
这是我要理解的文件,以供参考。
答案 0 :(得分:4)
通常
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"
在TH_CONCAT_...
中定义了lib/TH/THGeneral.h.in
:
#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
浮点数的函数实际上称为torch_floatTensor_elementSize
)。
我们真正想做的就是抽象一个类型参数,这里称为Real
。