【问题标题】:Address COM in OS X via FireMonkey/C++通过 FireMonkey/C++ 在 OS X 中寻址 COM
【发布时间】:2014-02-12 19:24:25
【问题描述】:

基于 COM 的 Blackmagic DeckLink API 可用于 Windows 和 OS X。我希望在 OS X 中解决它,但在 C++ 中使用 FireMonkey (FMX)。问题是他们的示例代码*是为 Cocoa 编写的,我不知道如何为 FireMonkey 重写它。有没有人有这方面的经验,有没有可能。

或者,有没有一种通用方法可以在 FireMonkey/OS X 中寻址具有 COM 接口的库?

这是 Cocoa 的部分代码,根据请求。

void    InitDeckLinkAPI (void)
{
    CFURLRef        bundleURL;

    bundleURL = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, CFSTR(kDeckLinkAPI_BundlePath), kCFURLPOSIXPathStyle, true);
    if (bundleURL != NULL)
    {
        gDeckLinkAPIBundleRef = CFBundleCreate(kCFAllocatorDefault, bundleURL);
        if (gDeckLinkAPIBundleRef != NULL)
        {
            gCreateIteratorFunc = (CreateIteratorFunc)CFBundleGetFunctionPointerForName(gDeckLinkAPIBundleRef, CFSTR("CreateDeckLinkIteratorInstance_0002"));
            gCreateAPIInformationFunc = (CreateAPIInformationFunc)CFBundleGetFunctionPointerForName(gDeckLinkAPIBundleRef, CFSTR("CreateDeckLinkAPIInformationInstance_0001"));
            gCreateOpenGLPreviewFunc = (CreateOpenGLScreenPreviewHelperFunc)CFBundleGetFunctionPointerForName(gDeckLinkAPIBundleRef, CFSTR("CreateOpenGLScreenPreviewHelper_0001"));
            gCreateCocoaPreviewFunc = (CreateCocoaScreenPreviewFunc)CFBundleGetFunctionPointerForName(gDeckLinkAPIBundleRef, CFSTR("CreateCocoaScreenPreview_0001"));
            gCreateVideoConversionFunc = (CreateVideoConversionInstanceFunc)CFBundleGetFunctionPointerForName(gDeckLinkAPIBundleRef, CFSTR("CreateVideoConversionInstance_0001"));
        }
        CFRelease(bundleURL);
    }
}

bool        IsDeckLinkAPIPresent (void)
{
    // If the DeckLink API bundle was successfully loaded, return this knowledge to the caller
    if (gDeckLinkAPIBundleRef != NULL)
        return true;

    return false;
}

IDeckLinkIterator*      CreateDeckLinkIteratorInstance (void)
{
    pthread_once(&gDeckLinkOnceControl, InitDeckLinkAPI);

    if (gCreateIteratorFunc == NULL)
        return NULL;

    return gCreateIteratorFunc();
}

*此处包含的内容太长,但您可以下载它here

【问题讨论】:

    标签: c++ macos com c++builder firemonkey


    【解决方案1】:

    在不支持本机 COM 的平台(例如 OS X)上,应提供 C 入口点来访问接口,并且在 DeckLink API 中有这样的工厂方法:

    IDeckLinkIterator *deckLinkIterator = CreateDeckLinkIteratorInstance();
    

    因此您可以在 C++Builder 中简单地使用 DeckLink API。但是有一个问题,C++Builder在sysmac.h中定义了一些COM类型如IUnknown(在System.hpp中包含)与CFPluginCOM.h中定义的相同类型冲突,如果你的项目包含System.hpp比如所有firemonkey项目编译器都会报错:

    [bccosx Error] sysmac.h(287): E2238 Multiple declaration for 'IUnknown'
    

    在DeckLink API的示例目录中有一个名为DeckControl的示例,它是一个控制台程序,您可以使用C++Builder编译它:

    1. 创建一个控制台项目并将 main.cpp 指定为项目源。
    2. 选择“无”作为目标框架
    3. 添加“OSX”平台

    项目编译成功。

    那么 Fmx 项目(使用 System.hpp)呢?
    创建一个包装单元(例如 bcb_deck),将所需的 API 放入其中。注意不要在单元头中包含“DeckLinkAPI.h”,这会导致与上述相同的问题,但将其放在cpp(bcb_deck.cpp)中,例如:

    bcb_deck.cpp:

    void* createDeckLinkIteratorInstance() // use camel case to prevent conflict
    {
        return (void*) CreateDeckLinkIteratorInstance();
    }
    
    bool deckLinkIteratorNext(void *hDeckLinkIterator, void *hDeckLink)
    {
        IDeckLinkIterator *deckLinkIterator = (IDeckLinkIterator*) hDeckLinkIterator;
        IDeckLink *deckLink = (IDeckLink*) hDeckLink;
    
        return deckLinkIterator->Next(&deckLink) == S_OK;
    }
    

    用法:

    #include "bcb_deck.h"
    void *hDeckLinkIterator, *hDeckLink;
    hDeckLinkIterator = createDeckLinkIteratorInstance();
    if (hDeckLinkIterator)
    {
        // Enumerate all cards in this system
        while (deckLinkIteratorNext(hDeckLinkIterator, hDeckLink))
        {
            // ...
        }
    }
    

    【讨论】:

    • 谢谢!我将不得不尝试一下,因为我看到了一些我不熟悉的东西,我也不知道我可以像支持普通 DLL 一样支持 COM。请注意,所有库都已经安装(这提出了我在哪里可以找到它们的问题)并且显然已经作为 dylib 提供。
    • 你能写一个示例代码来展示如何使用 DeckLink Api (Cocoa) 吗?
    • 当然,我添加了部分代码。对于所有代码,最好下载 SDK。
    • 好吧,你说“问题是他们的示例代码*是为 Cocoa 编写的”,不是,示例代码是为 C++(核心基础级别)编写的,并且可能由以下人员编译C++Builder,我错了吗?
    • 谢谢。无法访问 system.h 证明很困难,因为我需要找出字符串之类的等价物,显然是 CFStringRef。但是,当我使用它时,我无能为力,调试器甚至无法识别它(说模型名称是 8)。当我尝试将字符串转换为 char 时,在 CFStringGetLength() 处出现异常,这可能表明字符串无效。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-04-27
    • 1970-01-01
    • 2012-10-10
    • 2012-05-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多