如何使 Mac OS 组件管理器组件对其他进程可见?
这有点深奥,但这里肯定有几个人知道 OS X 的 Carbon 组件管理器是如何工作的。我制作了几个小应用程序来制作组件(请参阅 此处了解一些背景信息)。实际上,其中一个应用程序是直接来自 Apple 的示例程序,名为“Fiendishthngs”。它列出了组件管理器可用的所有组件。我的程序是一个简单的小东西,它注册一个组件,列出组件管理器拥有的所有组件,然后无限期地等待(以避免清除它注册的组件)。
在我的系统上,组件管理器正在跟踪 873 个组件(主要是一种另一种编解码器)。我的程序注册了一个组件,然后计数了 874 个组件,因为它本身只注册了一个,当然)。来源如下:
void RegisterBasicComponent()
{
ComponentDescription desc;
desc.componentType = kMyComponentType;
desc.componentSubType = kMyComponentSubType;
desc.componentManufacturer = kMyComponentManufacturer;
desc.componentFlags = 0;
desc.componentFlagsMask = cmpIsMissing;
ComponentRoutineUPP MyComponentRoutineUPP
= NewComponentRoutineUPP( &MyComponentRoutineProc );
// Handle name_handle = NewHandle( sizeof( kMyComponentName ) );
//strcpy( *(char**)name_handle, kMyComponentName );
//RegisterComponent( &desc, MyComponentRoutineUPP, registerComponentGlobal, name_handle, NULL, NULL );
Component component = RegisterComponent( &desc, MyComponentRoutineUPP, registerComponentGlobal, NULL, NULL, NULL );
if ( NULL != component )
printf("The registration seems to have worked!\n");
else
printf("Nope - didn't work for some reason.\n");
}
int main( void )
{
RegisterBasicComponent();
ComponentDescription looking;
// OSType componentType; /* A unique 4-byte code indentifying the command set */
// OSType componentSubType; /* Particular flavor of this instance */
// OSType componentManufacturer; /* Vendor indentification */
// UInt32 componentFlags; /* 8 each for Component,Type,SubType,Manuf/revision */
// UInt32 componentFlagsMask; /* Mask for specifying which flags to consider in search, zero during registration */
looking.componentType = kAnyComponentType;
looking.componentSubType = kAnyComponentSubType;
// looking.componentSubType = kComponentResourceType
looking.componentManufacturer = kAnyComponentManufacturer;
looking.componentFlags = 0;
looking.componentFlagsMask = cmpIsMissing;
long numComponents = CountComponents ( &looking );
printf("Found %ld components.\n", numComponents);
Component component = 0;
int i = 0;
while (true)
{
component = FindNextComponent(component, &looking);
if ( 0 == component )
break;
ComponentDescription desc;
Handle componentName = NewHandle(256);
Handle componentInfo = NewHandle(1024);
Handle componentIcon = 0;
OSErr err = GetComponentInfo( component,
&desc,
componentName,
componentInfo,
componentIcon );
if ( err != noErr )
{
printf("Couldn't find any info on component %d of %ld in list!\n", i
, numComponents);
break;
}
printf( "%d of %ld: '%c%c%c%c', '%c%c%c%c', '%c%c%c%c', '%s'\n",
i, numComponents,
SPLAT_WORD( desc.componentManufacturer ),
SPLAT_WORD( desc.componentType ),
SPLAT_WORD( desc.componentSubType ),
*componentName );
RecoverHandle( *componentName );
RecoverHandle( *componentInfo );
++i;
}
while (true)
{
printf("Waiting around for someone to use me...\n");
sleep( 3 );
}
}
无论如何,当我运行这个时,保持它运行(这样组件可能会在组件管理器中保持注册状态),然后运行 Fiendishthngs,Fiendishthngs 看不到我注册的测试组件 - 它只看到 873 个组件。传递到 RegisterComponent() 的“registerComponentGlobal”标志应该使该组件可供其他进程使用,但似乎出现了问题。
有什么想法吗?
This is a bit esoteric, but there have to be a few people here who know how OS X's Carbon Component Manager works. I've made a couple of little apps to play around with making Components (see here for some background). Actually, one of the apps is a sample program straight from Apple called 'Fiendishthngs'. It lists all the Components that the Component Manager is making available. My program is a simple little thing that registers a Component, lists all the Components that the Component Manager has, and then waits around indefinately (to avoid purging the Component that it registered).
On my system, the Component Manager is tracking 873 Components (mostly codecs of one sort of another). My program that registers a Component registers it, and then counts 874 Components because it just registered one itself, of course). Here's the source:
void RegisterBasicComponent()
{
ComponentDescription desc;
desc.componentType = kMyComponentType;
desc.componentSubType = kMyComponentSubType;
desc.componentManufacturer = kMyComponentManufacturer;
desc.componentFlags = 0;
desc.componentFlagsMask = cmpIsMissing;
ComponentRoutineUPP MyComponentRoutineUPP
= NewComponentRoutineUPP( &MyComponentRoutineProc );
// Handle name_handle = NewHandle( sizeof( kMyComponentName ) );
//strcpy( *(char**)name_handle, kMyComponentName );
//RegisterComponent( &desc, MyComponentRoutineUPP, registerComponentGlobal, name_handle, NULL, NULL );
Component component = RegisterComponent( &desc, MyComponentRoutineUPP, registerComponentGlobal, NULL, NULL, NULL );
if ( NULL != component )
printf("The registration seems to have worked!\n");
else
printf("Nope - didn't work for some reason.\n");
}
int main( void )
{
RegisterBasicComponent();
ComponentDescription looking;
// OSType componentType; /* A unique 4-byte code indentifying the command set */
// OSType componentSubType; /* Particular flavor of this instance */
// OSType componentManufacturer; /* Vendor indentification */
// UInt32 componentFlags; /* 8 each for Component,Type,SubType,Manuf/revision */
// UInt32 componentFlagsMask; /* Mask for specifying which flags to consider in search, zero during registration */
looking.componentType = kAnyComponentType;
looking.componentSubType = kAnyComponentSubType;
// looking.componentSubType = kComponentResourceType
looking.componentManufacturer = kAnyComponentManufacturer;
looking.componentFlags = 0;
looking.componentFlagsMask = cmpIsMissing;
long numComponents = CountComponents ( &looking );
printf("Found %ld components.\n", numComponents);
Component component = 0;
int i = 0;
while (true)
{
component = FindNextComponent(component, &looking);
if ( 0 == component )
break;
ComponentDescription desc;
Handle componentName = NewHandle(256);
Handle componentInfo = NewHandle(1024);
Handle componentIcon = 0;
OSErr err = GetComponentInfo( component,
&desc,
componentName,
componentInfo,
componentIcon );
if ( err != noErr )
{
printf("Couldn't find any info on component %d of %ld in list!\n", i
, numComponents);
break;
}
printf( "%d of %ld: '%c%c%c%c', '%c%c%c%c', '%c%c%c%c', '%s'\n",
i, numComponents,
SPLAT_WORD( desc.componentManufacturer ),
SPLAT_WORD( desc.componentType ),
SPLAT_WORD( desc.componentSubType ),
*componentName );
RecoverHandle( *componentName );
RecoverHandle( *componentInfo );
++i;
}
while (true)
{
printf("Waiting around for someone to use me...\n");
sleep( 3 );
}
}
Anyways, when I run this, keep it running (so the Component would presumably stay registered with the Component Manager), and then run Fiendishthngs, Fiendishthngs can't see my test Component that I register - it only sees 873 Components. The 'registerComponentGlobal' flag passed into RegisterComponent() is supposed to make the Component available to other processes, but it seems like something is going awry.
Any ideas?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
好吧,我把这个问题抛在脑后,接受了 OS X 的组件管理器可能不再支持“全局”选项的事实。
这真的很有意义。使您的组件从您的进程到其他进程“全局”需要进程外调用编组,就像 OS X 中的 RPC 一样。另一方面,在 OS 9 及更早版本中,考虑到所有这些,这将是非常有意义的进程位于公共地址空间中。对于 OS 9,让一个组件对所有进程全局可用是很简单的。
无论如何,今天我正在反汇编 RegisterComponentFileRefEntries() ,其中相关代码似乎驻留在其中,果然,我在函数的前言中看到了这一点(注释是我的):
RegisterComponentFileRefEntries 的签名是
RegisterComponentFileRefEntries 唯一的 2 个参数困扰的是spec(在ebp+0x8)和toRegister(在ebp+0x10)。 global(位于 ebp+0xc)和 registerCount(位于 ebp+0x14)被完全忽略。
Well, I left this issue behind, resigning myself to the fact that OS X's Component Manager probably doesn't support the 'global' option anymore.
This would make a lot of sense, really. Making your component 'global' from your process to other processes would require out-of-process call marshalling, like with RPC, with OS X. On the other hand, in OS 9 and earlier, it would make perfect sense, given that all processes lived in a common address space. For OS 9 it would be trivial to make a component globally available to all processes.
Anyways, today I was disassembling RegisterComponentFileRefEntries() where the relevant code seems to reside, and sure enough, I saw this in the pre-amble to the function (the comments are mine):
The signature for RegisterComponentFileRefEntries is
The only 2 parameters that RegisterComponentFileRefEntries bothers with are spec (at ebp+0x8) and toRegister (at ebp+0x10). global (at ebp+0xc) and registerCount (at ebp+0x14) are completely ignored.