I suspect a bug here, especially since it does not crash when using Real Studio 2012r2.1, but it does with Xojo 2016r4.1:
Consider this sample code:
[code]soft declare sub checkForUpdates lib “@executable_path/…/Frameworks/Sparkle.framework/Sparkle” selector “checkForUpdates:” (obj_id as Ptr, sender as Ptr)
static b as boolean
if b then
checkForUpdates (nil, nil)
end if[/code]
The “checkForUpdates” will never execute. Regardless, when you place this code into an app, the app crashes at launch with the report:
[quote]dyld: launch, loading dependent libraries
Dyld Error Message:
Library not loaded: @executable_path/…/Frameworks/Sparkle.framework/Sparkle
Referenced from: /private/var/folders/*/soft_declare_test.debug.app/Contents/MacOS/soft_declare_test.debug
Reason: image not found
[/quote]
This is not right, IMO. If I a “soft declare”, the lib should not get attempted to be loaded until I actually access it. And in RS this behaved as expected.
Oh, you know what, try putting the declare inside the if statement and see if that makes it less temperamental.
static b as boolean
if b then
soft declare sub checkForUpdates lib "@executable_path/../Frameworks/Sparkle.framework/Sparkle" selector "checkForUpdates:" (obj_id as Ptr, sender as Ptr)
checkForUpdates (nil, nil)
end if
This can be gotten around by changing the library to something like Foundation and loading the Sparkle framework yourself. The library name for Objective-C declares has no relation to how the function gets called. It just is used for recording the dependency and ensuring the library gets loaded.
And here’s the code to load a framework manually. I already did that anyway:
Private Shared Function loadBundle(f as FolderItem) As Boolean
#if TargetMacOS
declare function CFURLCreateWithString lib "Cocoa" (allocator as Ptr, URLString as CFStringRef, baseURL as Ptr) as Ptr
declare function bundleWithURL lib "Cocoa" selector "bundleWithURL:" (cls as Ptr, url as Ptr) as Ptr
declare function load lib "Cocoa" selector "load" (obj as Ptr) as Boolean
declare sub CFRelease lib "Carbon" (cf as Ptr)
if f is nil then return false
dim fileURL as String = f.URLPath
dim bundleURL as Ptr = CFURLCreateWithString(nil, fileURL, nil)
if bundleURL = nil then return false
dim cls as Ptr = Cocoa.NSClassFromString ("NSBundle")
dim bundle as Ptr = bundleWithURL (cls, bundleURL)
CFRelease bundleURL
return load (bundle)
#endif
End Function
To fix that, add this line to the declares in the function:
declare function NSClassFromString lib "Cocoa" (aClassName as CFStringRef) as Ptr
And then change Cocoa.NSClassFromString into NSClassFromString
Then, instead of using “@executable_path/…/Frameworks/Sparkle.framework” as the lib path to the framework, use “Foundation” as the Lib name, and invoke
if not loadBundle App.ExecutableFile.Parent.Child("Frameworks").Child("Sparkle.framework") then
// lib is missing
return
end
before calling into any of the framework ObjC methods.