[英]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 级深度轨道相结合并渲染每一帧。
回放提供了输出选择:
它运行在 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.