将结构更改为类(以及其他类型更改)和ABI/代码生成

Changing struct to class (and other type changes) and ABI/code generation

本文关键字:ABI 类型 代码生成 结构 及其他      更新时间:2023-10-16

这是一个公认的、规范的参考问题,在c++中,当手工编写代码时,结构体和类几乎可以互换。

然而,如果我想链接到现有的代码,如果我重新声明一个结构作为类,或者反之亦然,在原始代码生成后的头文件中,我能期望它有任何区别(即中断,鼻恶魔等)吗?

所以情况是类型被编译为一个结构体(或类),我然后将头文件更改为其他声明,然后将其包含在我的项目中。

现实世界的用例是,我是自动生成代码与SWIG,它产生不同的输出取决于它是否给定结构或类;我需要将其中一个更改为另一个以使其输出正确的接口。

示例如下(irrlight, SVertexManipulator.h) -给定:

struct IVertexManipulator
{
};

我机械地将其重新声明为:

/*struct*/class IVertexManipulator
{public:
};

原始库使用原始头文件编译,不受影响。包装器代码是使用修改后的表单生成的,并使用它们进行编译。然后将两者连接到同一个程序中一起工作。假设我对两个库使用完全相同的编译器。

这类东西是未定义的吗?"未定义",但期望在现实世界的编译器上工作?完美的允许吗?

我正在做的其他类似更改包括从参数中删除一些默认值(以防止歧义),并从几个类型对SWIG不可见的类中删除字段声明(这改变了类的结构,但是我的理由是生成的代码应该需要这些信息,仅用于链接到成员函数)。再问一次,这会造成多大的破坏?

。IGPUProgrammingServices.h:

s32 addHighLevelShaderMaterial(
    const c8* vertexShaderProgram,
    const c8* vertexShaderEntryPointName/*="main"*/,
    E_VERTEX_SHADER_TYPE vsCompileTarget/*=EVST_VS_1_1*/,
    const c8* pixelShaderProgram=0,
...

CIndexBuffer.h:

public:
    //IIndexList *Indices;

…以此类推。其他变化包括用模板参数类型的类型定义替换模板参数类型,并从一些结构体中删除packed属性。同样,如果改变的结构声明从未在机器码中实际使用(只是为了生成链接到主库中的访问器函数的名称),似乎应该没有问题,但是这种情况可靠吗?曾经的情况?

这是技术上未定义的行为。

3.2/5:

类类型可以有多个定义,[…]或者其他应该在头文件中定义的东西…]在程序中,只要每个定义出现在不同的翻译单元中,并且提供定义满足以下要求。给定在多个翻译单元中定义的名为D的实体,则

  • D的每个定义应由相同的令牌序列组成;和

  • ……

…如果D的定义满足所有这些要求,那么程序将表现得好像只有一个D的定义。如果D的定义不满足这些要求,那么行为是未定义的。

本质上,您将第一个令牌从struct更改为class,并根据需要插入令牌public:。《标准报》不允许。

但是在我所熟悉的所有编译器中,这在实践中是可以的。


我正在做的其他类似的更改包括从参数中删除一些默认值(以防止歧义)

如果声明不在类定义中,那么

实际上在形式上是允许的。一个TU内不同的翻译单元甚至不同的作用域可以定义不同的默认函数参数。所以你在那里可能也很好。

其他更改包括用模板参数的typedefs替换一些模板参数类型

也正式允许在类定义之外:使用不同命名方式的函数的两个声明引用同一个函数。

…删除字段声明…从一些结构体中删除打包属性

现在你处于非常危险的境地。我不熟悉SWIG,但是如果您要做这种事情,您最好确保使用这些"错误"的代码。没有定义:

  • 创建或销毁类类型

    的对象
  • 定义继承或包含类类型

    成员的类型
  • 使用类

    的非静态数据成员
  • 调用使用类

    的非静态数据成员的内联函数或模板函数
  • 调用类类型或派生类型的virtual成员函数

  • 尝试查找sizeofalignof的类类型