繁体   English   中英

如何最好地在不支持的 C++ 方言中实现函数指针?

[英]How best to implement function pointers in a C++ dialect that does not support it?

例如,OpenCL 不支持函数指针。 一些针对嵌入式硬件的工具链也没有。 RPC 需要一个等效于跨不相交堆的函数指针。 因此,希望有足够的现有技术来提供一个已知的(虽然对我来说还不是)好的解决方案。

我已经将这个问题标记为“C++”,尽管我知道一种看起来像 C++ 但没有函数指针的语言实际上不是 C++。 它仍然是最接近的。 我有模板等可用,只是没有太多的运行时支持。

例如,可以要求程序员为他们希望通过指针传递的每个函数分配一个枚举,并编写一个直接调用每个函数的开关。 加上传递该枚举的元素,而不是函数的地址,并使用联合做一些事情来处理参数的变化。

或者,可以散列函数的符号名称(半自动分配值)并根据这些散列编写一个开关。 这就是我今天要做的,但是我想消除自定义编译器支持。

手动写出任何一个开关,在需要时添加一个条目,都不是很好。 因此,也许可以通过在全局数组上展开循环来构建 if/else 链。

这里没有类型安全,所以也许它应该是每个函数类型的单独散列/枚举/数组/其他。 这将删除一些工会。

经过几个月的反复思考,我还没有看到一个干净/可维护的解决方案(这不是定制的编译器传递)。 欢迎提出想法。

您正处于使用开关的正确轨道上。

早在 1999 年至 2001 年,我是一个项目的主要开发人员,该项目此后 几乎从网络上消失了,在 Apple 的 Quicktime 中进行实时立体 3D 渲染。

它提供了一种自定义电影格式,采用标准 2D 视频,将其与 256 级深度轨道相结合并渲染每一帧。

回放提供了输出选择:

  • 不同种类的彩色镜片眼镜:青红、红绿等,在新奇产品中经常出现,其中 3D 是通过遮蔽偏移实现的
  • 不同颜色的单色镜片,其中颜色仅用于提供深度效果 - 对于精细的科学和采矿数据非常有用,例如观察岩石
  • 同步快门 LCD 眼镜,以 60Hz 运行,插入到 120Hz CRT 中,以及
  • 非常早期的无眼镜显示器(每个约 10 万美元,用于会议)。

它运行在 Windows 和那个时代的经典 Mac 设备上,以 24fps 进行实时渲染。 在 G3 iMac 350MHz PowerPC 等硬件上并不容易。

它还能够调整每帧的深度渲染效果。 您可以选择让电影出现屏幕前面后面,并根据事物看起来有多远来调整深度幅度

所以,加上不同的电影格式,有很多东西可以打开,这些东西可能会不断变化。

我认为这是我编程生涯的顶峰。 这是一个有趣且极具挑战性的项目,研究如何在 Quicktime 中提供这种 3D 渲染,以及在技术上获得性能的挑战。 在 2000 年的 WWDC 上,Apple QuickTime 工程师对我们做到了表示祝贺和震惊。 这一切都是使用标准 QuickTime API 完成的,并且运行非常稳健,没有涉及任何黑客攻击。

下面的大代码示例展示了我如何使用模板和开关。 嵌套的 switch 语句分解了上面讨论的每帧变量。

嵌套开关每渲染一帧运行一次。 它们导致调用一个独特的函数,该函数循环渲染每个像素——我认为模板生成了大约 700 种不同的变化。

我记得在优化模板函数的项目中途对 CodeWarrior 编译器进行了重大升级。 我们的编译时间增加了 4 倍,但生成的代码更小、速度更快。

// from rendererersP.h

/**
this template definition provides the implementation of the
stereo pair algorithm for the argument class types.

pass a single StereoRenderPars struct which tells the function
about the source and destination data.
*/
template<class ImageFormat, 
         class DepthFormat, 
         class GlassFormat, 
         class DestinationFormat>
void RenderStereoPair (StereoRenderPars *rp)
{


// from render_switch.cpp
// the entry point for stereo
int
renderStereo(GlassType gt, ImageFormat sf, StereoRenderPars *rp, bool outputGrey)
{
  int status = 0;

  switch (gt)    // The GT Stringers!
  {
    case gtRLeftBGRight :
      {
        switch (outputGrey)
        {
          case true :
            {
              switch (sf)
              {
                case ifRGB :
                  RenderStereoPair<ImageGrayRGB, DepthUnsigned24, GlassRLeftBGRight, ImageGrayRGB>(rp);
                  break;
                case ifBGR :
                  RenderStereoPair<ImageGrayBGR, DepthUnsigned24, GlassRLeftBGRight, ImageGrayBGR>(rp);
                  break;
                case ifARGB :
                  RenderStereoPair<ImageGrayARGB, DepthUnsigned32, GlassRLeftBGRight, ImageGrayARGB>(rp);
                  break;
                case ifBGRA :
                  RenderStereoPair<ImageGrayBGRA, DepthUnsigned32, GlassRLeftBGRight, ImageGrayBGRA>(rp);
                  break;
                case if555RGB :
                  RenderStereoPair<ImageGray555RGB, DepthUnsigned16, GlassRLeftBGRight, ImageGray555RGB>(rp);
                  break;
                case if565RGB :
                  RenderStereoPair<ImageGray565RGB, DepthUnsigned16, GlassRLeftBGRight, ImageGray565RGB>(rp);
                  break;
                default :
                  status = 1;
              }
            }
                break;
          case false :
            {
              switch (sf)
              {
                case ifRGB :
                  RenderStereoPair<ImageRGB, DepthUnsigned24, GlassRLeftBGRight, ImageRGB>(rp);
                  break;
                case ifBGR :
                  RenderStereoPair<ImageBGR, DepthUnsigned24, GlassRLeftBGRight, ImageBGR>(rp);
                  break;
                case ifARGB :
                  RenderStereoPair<ImageARGB, DepthUnsigned32, GlassRLeftBGRight, ImageARGB>(rp);
                  break;
                case ifBGRA :
                  RenderStereoPair<ImageBGRA, DepthUnsigned32, GlassRLeftBGRight, ImageBGRA>(rp);
                  break;
                case if555RGB :
                  RenderStereoPair<Image555RGB, DepthUnsigned16, GlassRLeftBGRight, Image555RGB>(rp);
                  break;
                case if565RGB :
                  RenderStereoPair<Image565RGB, DepthUnsigned16, GlassRLeftBGRight, Image565RGB>(rp);
                  break;
                default :
                  status = 1;
              }
            }
        }
      }
      break;
    case gtBGLeftRRight :
      {
        switch (outputGrey)
        {
          case true :
            {
              switch (sf)
              {
                case ifRGB :
                  RenderStereoPair<ImageGrayRGB, DepthUnsigned24, GlassBGLeftRRight, ImageGrayRGB>(rp);
                  break;
                case ifBGR :
                  RenderStereoPair<ImageGrayBGR, DepthUnsigned24, GlassBGLeftRRight, ImageGrayBGR>(rp);
                  break;
                case ifARGB :
                  RenderStereoPair<ImageGrayARGB, DepthUnsigned32, GlassBGLeftRRight, ImageGrayARGB>(rp);
                  break;
                case ifBGRA :
                  RenderStereoPair<ImageGrayBGRA, DepthUnsigned32, GlassBGLeftRRight, ImageGrayBGRA>(rp);
                  break;
                case if555RGB :
                  RenderStereoPair<ImageGray555RGB, DepthUnsigned16, GlassBGLeftRRight, ImageGray555RGB>(rp);
                  break;
                case if565RGB :
                  RenderStereoPair<ImageGray565RGB, DepthUnsigned16, GlassBGLeftRRight, ImageGray565RGB>(rp);
                  break;
                default :
                  status = 1;
              }
            }
                break;

          case false :
            {
              switch (sf)
              {
                case ifRGB :
                  RenderStereoPair<ImageRGB, DepthUnsigned24, GlassBGLeftRRight, ImageRGB>(rp);
                  break;
                case ifBGR :
                  RenderStereoPair<ImageBGR, DepthUnsigned24, GlassBGLeftRRight, ImageBGR>(rp);
                  break;
                case ifARGB :
                  RenderStereoPair<ImageARGB, DepthUnsigned32, GlassBGLeftRRight, ImageARGB>(rp);
                  break;
                case ifBGRA :
                  RenderStereoPair<ImageBGRA, DepthUnsigned32, GlassBGLeftRRight, ImageBGRA>(rp);
                  break;
                case if555RGB :
                  RenderStereoPair<Image555RGB, DepthUnsigned16, GlassBGLeftRRight, Image555RGB>(rp);
                  break;
                case if565RGB :
                  RenderStereoPair<Image565RGB, DepthUnsigned16, GlassBGLeftRRight, Image565RGB>(rp);
                  break;
                default :
                  status = 1;
              }
            }
        }
      }
      break;

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM