如何实现返回运行时确定的大型结构类型的 IMP 函数?

发布于 2024-10-27 10:21:42 字数 1383 浏览 1 评论 0原文

背景:CamelBones 在 Objective-C 运行时注册 Perl 类。 为此,每个 Perl 方法都注册到相同的 IMP 功能;该函数检查其自身 &要查找的 _cmd 参数 调用哪个 Perl 方法。

多年来,这种方法一直运作良好,对于那些 使用 objc_msgSend 调度。但现在我想添加对 从 Perl 方法返回浮点和大型结构类型。 浮点并不难;我将简单地编写另一个返回的 IMP double,用于处理通过 objc_msgSend_fpret 分派的消息。

问题是如何处理 objc_msgSend_stret。写一个 为每个可能的结构返回类型单独的 IMP 是不切实际的,对于 有两个原因:首先,因为即使我这样做只是针对结构类型 这是在编译时已知的,这是一个荒谬的函数数量。 其次,因为我们正在讨论一个可以与任何任意 Objective-C 和 Java 框架相链接的框架。 Perl 代码,在编译框架时我们知道所有潜在的结构类型。

我希望做的是编写一个可以处理任何返回的 IMP 通过 objc_msgSend_stret 分派的类型。我可以把它写成 返回void,并将指针参数传递给返回缓冲区,例如 旧的 objc_msgSend_stret 已声明?即使那件事发生了 现在工作了,以后还能继续工作吗?

感谢您的任何建议 - 我一直在为这个问题绞尽脑汁。 :-)

更新:

这是我从 Apple 的一位运行时工程师在他们的 objc 语言邮件列表中收到的建议:

必须编写汇编代码来处理 本案。

您的建议在某些方面失败了 架构,其中 ABI 代表“功能” 返回 void 并带有指向 a 的指针 结构作为第一个参数”不同 来自“返回结构的函数”。 (在 i386 上,结构地址被弹出 由调用者从堆栈中取出 案例中的被调用者在另一个案例中 案例。)这就是为什么原型 objc_msgSend_stret 已更改。

汇编代码将捕获 结构返回地址,将其偷偷放入 非结构返回 C 函数调用 在不打扰其他人的情况下 参数,然后做正确的事情 退出时特定于 ABI 的清理(ret $4 在 i386 上)。或者,组件 代码可以捕获所有 参数。货运机械 做这样的事情。那个代码 可能在开源 CoreFoundation 中 如果你想看看有什么技巧 看起来像。

我将保留这个问题,以防有人集思广益,提出更好的想法,但由于这个问题直接来自苹果自己的“运行时管理员”,我认为这可能是我可能得到的最权威的答案。我想是时候掸掉 x86 参考手册上的灰尘并清除我的汇编器上的锈迹了……

Background: CamelBones registers Perl classes with the Objective-C runtime.
To do this, every Perl method is registered with the same IMP
function; that function examines its self & _cmd arguments to find
which Perl method to call.

This has worked well enough for several years, for messages that were
dispatched with objc_msgSend. But now I want to add support for
returning floating-point and large struct types from Perl methods.
Floating-point isn't hard; I'll simply write another IMP that returns
double, to handle messages dispatched with objc_msgSend_fpret.

The question is what to do about objc_msgSend_stret. Writing a
separate IMP for every possible struct return type is impractical, for
two reasons: First, because even if I did so only for struct types
that are known at compile-time, that's an absurd number of functions.
And second, because we're talking about a framework that can be linked against any arbitrary Objective-C & Perl code, we don't know all the potential struct types when the framework is being compiled.

What I hope to do is write a single IMP that can handle any return
type that's dispatched via objc_msgSend_stret. Could I write it as
returning void, and taking a pointer argument to a return buffer, like
the old objc_msgSend_stret was declared? Even if that happened to
work for now, could I rely on it continuing to work in the future?

Thanks for any advice - I've been racking my brain on this one. :-)

Update:

Here's the advice I received from one of Apple's runtime engineers, on their objc-language mailing list:

You must write assembly code to handle
this case.

Your suggestion fails on some
architectures, where ABI for "function
returning void with a pointer to a
struct as the first argument" differs
from "function returning a struct".
(On i386, the struct address is popped
from the stack by the caller in one
case and by the callee in the other
case.) That's why the prototype for
objc_msgSend_stret was changed.

The assembly code would capture the
struct return address, smuggle it into
non-struct-return C function call
without disturbing the rest of the
parameters, and then do the right
ABI-specific cleanup on exit (ret $4
on i386). Alternatively, the assembly
code can capture all of the
parameters. The forwarding machinery
does something like this. That code
might be in open-source CoreFoundation
if you want to see what the techniques
look like.

I'll leave this question open, in case someone brainstorms a better idea, but with this coming directly from Apple's own "runtime wrangler," I figure it's probably as authoritative an answer as I'm likely to get. Time to dust off the x86 reference manuals and knock the rust off my assembler-fu, I guess...

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

倾城月光淡如水﹏ 2024-11-03 10:21:42

看来苹果工程师是对的:唯一的出路就是汇编代码。以下是一些有用的入门指南:

希望它有所帮助。

It seems that the Apple engineer is right: the only to way to go is assembly code. Here are some usefull pointers to getting started:

  • From the Objective-C runtime code: The i386 and x86_64 hand-crafted messenger assmbly stubs for the various messaging methods.
  • An SO answer that provides an overview of the dispatching.
  • A in-depth review of the dispatching mecanism with a line-by-line analysis of the assembly code

Hope it helps.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文