0

这有点深奥,但这里肯定有几个人知道 OS X 的 Carbon Component Manager 是如何工作的。我制作了几个小应用程序来制作组件(有关背景信息,请参见此处)。实际上,其中一个应用程序是直接来自 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' 标志应该使 Component 可用于其他进程,但似乎出现了问题。

有任何想法吗?

4

1 回答 1

3

好吧,我把这个问题抛在脑后,让自己接受 OS X 的组件管理器可能不再支持“全局”选项的事实。

这会很有意义,真的。让你的组件从你的进程到其他进程“全局”需要进程外调用编组,就像使用 RPC,使用 OS X。另一方面,在 OS 9 和更早版本中,这将是非常有意义的,因为所有进程生活在一个公共地址空间中。对于 OS 9,让一个组件对所有进程全局可用是微不足道的。

无论如何,今天我正在拆卸相关代码似乎所在的 RegisterComponentFileRefEntries() ,果然,我在函数的序言中看到了这一点(评论是我的):

0x9841a026  <+0018>  mov    eax, DWORD PTR [ebp+0x8]        // load param spec
0x9841a029  <+0021>  mov    DWORD PTR [ebp-0xdc],eax        // local spec = param spec
0x9841a02f  <+0027>  mov    edx,DWORD PTR [ebp+0x10]        // load param toRegister
0x9841a032  <+0030>  mov    DWORD PTR [ebp-0xe0],edx        // local toRegister = param toRegister

RegisterComponentFileRefEntries 的签名是

extern OSErr 
RegisterComponentFileEntries(
  const FSSpec *                spec,
  short                         global,
  const ComponentDescription *  toRegister,          /* can be NULL */
  UInt32                        registerCount)   

RegisterComponentFileRefEntries 唯一需要考虑的两个参数是 spec(在 ebp+0x8)和 toRegister(在 ebp+0x10)。global(在 ebp+0xc)和 registerCount(在 ebp+0x14)被完全忽略。

于 2009-12-27T00:45:43.547 回答