通过 Firemonkey 访问第三方 Mac API

Accessing a third party Mac API through Firemonkey

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

Plist 文件提到

    <key>CFBundleExecutable</key>

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

并且捆绑包包含一个没有文件扩展名但 'kind' 为 'Unix executable'

的文件

包含文件包含以下(简化的)代码,用于在 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 executable' 会不会只是一个 DYLIB?

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

如果显示 Mach-O 64-bit bundle,则您必须使用 dlopen()dlsym() 来访问其导出的函数。
如果它说 Mach-O 64-bit dynamically linked shared library,那么它是一个共享库,它可以在编译时被 linked 反对。

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

来反对它

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

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

然后当 linking 时,您将使用 -L some/path -l something