函数声明中不熟悉的C语法



目前正在研究一些对我来说毫无意义的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

这是我试图理解的文件,以供参考。

正常

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)

因此CCD_ 9被定义为在包括CCD_ 10之前的宏。

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没有模板(也没有名称空间(,所以获得这样的"通用"代码的唯一方法是手动使用宏和预处理技巧(以及手动"装饰"名称;例如,用于float的elementSize函数实际上称为torch_floatTensor_elementSize(。

我们真正想做的是对一个类型参数进行抽象,这里称为Real

最新更新