首页 > 解决方案 > 通过 Firemonkey 访问第三方 Mac API

问题描述

我有一个硬件制造商提供的 SDK,它提供 Windows 和 Mac API。在 Windows 中,这是一个标准的 COM DLL。在 Mac 上,它位于库中的捆绑包中。有人可以给我一个关于如何从 Firemonkey 应用程序访问功能的起点吗?

Plist 文件提到

    <key>CFBundleExecutable</key>

    <key>CFBundlePackageType</key>
    <string>BNDL</string>

并且该捆绑包包含一个没有文件扩展名但具有“Unix可执行文件”的“种类”的文件

包含文件包含以下(删节)代码,用于从 XCode 中的 C++ 访问 API:

typedef IDiscovery* (*CreateDiscoveryFunc)(void);

static pthread_once_t           gOnceControl            = PTHREAD_ONCE_INIT;
static CreateDiscoveryFunc      gCreateDiscoveryFunc    = NULL;

static void InitAPI (void)
{
    bundleURL = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, CFSTR(kAPI_BundlePath), kCFURLPOSIXPathStyle, true);
    if (bundleURL != NULL)
    {
        gBundleRef = CFBundleCreate(kCFAllocatorDefault, bundleURL);
        if (gBundleRef != NULL)
        {
            gCreateDiscoveryFunc = (CreateDiscoveryFunc)CFBundleGetFunctionPointerForName(gBundleRef, CFSTR("GetDiscoveryInstance"));
        }
        CFRelease(bundleURL);
    }
}

IDiscovery*             CreateDiscoveryInstance (void)
{
    pthread_once(&gOnceControl, InitAPI);
    
    if (gCreateDiscoveryFunc == NULL)
        return NULL;

    return gCreateDiscoveryFunc();
}

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
    mDiscovery = NULL;
    mDevice = NULL;
    
    mDiscovery = CreateDiscoveryInstance();
    if (! mDiscovery)
    {
        /* Show an alert to say the API may not be installed, and quit program */
    } 

    NSString* address = [mAddressTextField stringValue];    
    ConnectToFailure    failReason;
    
    HRESULT hr = mDiscovery->ConnectTo((CFStringRef)address, &mDevice, &failReason);

}

如果我能获得 mDevice 对象,那么我应该能够获得使用 API 所需的所有其他对象。

这个“Unix 可执行文件”可能只是一个 DYLIB 吗?

标签: macosdelphifiremonkeydylib

解决方案


在该二进制文件上运行file path/to/file,它应该会告诉你它是什么。

如果它显示Mach-O 64-bit bundle,那么您将不得不使用dlopen()dlsym()访问其导出的函数。
如果它说Mach-O 64-bit dynamically linked shared library,那么它是一个共享库,可以在编译时链接。

不过值得注意的是,您的二进制文件没有扩展名这一事实让我认为它是“框架”的形式。也就是说,它将具有共享库的格式,但路径为some/path/SomeName.framework/Versions/Current/SomeName. 如果是这样,您可以使用-F some/path -framework SomeName.

如果二进制文件不是框架的形式,只是一个没有后缀的共享库,那么链接到它会有点痛苦,因为 clang/ld64 只接受lib<string>.dylibor lib<string>.tbd。重命名库会使其安装名称无效,但编译器工具链需要它才能找到它。
如果您确实处于这种情况下,那么最简单的解决方法是从您的 dylib 中创建一个 tbd 文件(这只是一个文本文件,列出了 dylib 的所有链接信息,可用于动态链接)。为此,您将使用:

xcrun tapi stubify -o some/path/libsomething.tbd path/to/binary

然后在链接时,你会使用-L some/path -l something.


推荐阅读