Use framework "Custom.framework" fails

use framework “…” fails. The error display in Script Debugger is:

 "+[CocoaFromApplescript hello]: unrecognized selector sent to class 0x1124f3150"

Details
As a proof of concept, I have successfully made use of the FScript.framework from AppleScript as follows:

use framework “FScript”
set myBool to current application’s FSBoolean’s fsTrue

Script Debugger shows the value of myBool as:
(True) YES


Trying to mirror the successful use of FScript.framework, I have used Xcode to build the framework:
CocoaFromApplescript
with a few methods:
char* hello();
CGPoint mouseMove(CGFloat x, CGFloat y, bool click);
+ (void) EXAMPLEmouseMove;

The build framework is installed in /Library/Frameworks and successfully tested with calls from an Xcode project:

  • (IBAction) Button1:sender
    {
    [sender setEnabled:FALSE]; // disable subsequent click until the return from the action call
    [CocoaFromApplescript EXAMPLEmouseMove];
    hello();
    mouseMove(50, 80, false);
    [sender setEnabled:TRUE];
    }

But the attempt to test the MyCocoa methods from AppleScript fail (using the same syntax that works for FScript):

use framework " CocoaFromApplescript"
current application’s CocoaFromApplescript’s hello() – “+[CocoaFromApplescript hello]: unrecognized selector sent to class 0x1124f3150”
current application’s CocoaFromApplescript’s EXAMPLEmouseMove – “Can’t get MyCocoa of CocoaFromApplescript.”


Inspecting my framework, CocoaFromApplescript (using the terminal command ‘nm’), it appears to have accessible methods just like the FScript framework. And as noted above, my CocoaFromApplescript.framework behaves as expected when its routines are called from my test application:

In lieu of getting this framework strategy to work, maybe there is a simpler way to be able to call a custom class method from an AppleScript routine that was called from an objc app?

Hopefully someone has grappled successfully with this and can point me in the right direction.

Thanks in advance.

-Denis

Unless you’ve mis-typed, your char* hello() is not a method but a function. To make functions accessible, you need to add details of them to the framework’s .scriptingbridge file, which is basically undocumented and a pain. You’d be better to just wrap it in a method. And don’t return *char — AS is only going to understand an NSString. (The bridge may convert it, but as you’re in control, better not to risk it failing).

Right - I don’t want to go down the scripting bridge rabbit hole! Actually, I had also tried to get my method to work:

 + (void) EXAMPILEmouseMove;

called like this:

current application’s CocoaFromApplescript’s EXAMPLEmouseMove

but after a slight pause, this gives a different error:

 "Can’t get EXAMPLEmouseMove of CocoaFromApplescript."

Susequent to the above attempts I have re-organized things a bit - I rrenamed EXAMPLEmouseMove to EXAMPLE_MouseMove and moved its implementation into MyMethods.m. The MyMethods.h file is included into CocoaFromApplescript.h. So now things are organised just like the "proof of concept’, FScript.framework.

Still no luck. So far, I haven’t been able to spot any difference in syntax when comparing to the "proof of concept’:

current application’s FSBoolean’s fsTrue

or

set theContext to current application’s FSBoolean
theContext’s fsTrue

which both work as expected, but my test which fails:

set theContext to current application’s MyMethods --> (Class) MyMethods, «class ocid» id «data optr0000000050A19F1001000000»
theContext’s EXAMPLE_MouseMove --> ERROR “Can’t get EXAMPLE_MouseMove of «class ocid» id «data optr0000000050A19F1001000000»”

I am running OS 10.13, using Xcode 10.1. Both my CocoaFromApplescript.framework and FScript.framework are un-signed and both are located in /Library/Frameworks (and both frameworks are listed in script debuggers’s open files list).

It seems like CocoaFromApplescript.framework is structured correctly:

nm CocoaFromApplescript

0000000000000e30 t +[MyMethods EXAMPLE_MouseMove]
U _CFRelease
U _CGEventCreate
U _CGEventCreateMouseEvent
U _CGEventGetLocation
U _CGEventPost
0000000000000e00 t _CGPointMake
0000000000000f78 S _CocoaFromApplescriptVersionNumber
0000000000000f40 S _CocoaFromApplescriptVersionString
U _NSLog
0000000000001150 S OBJC_CLASS$_MyMethods
U OBJC_CLASS$_NSObject
0000000000001128 S OBJC_METACLASS$_MyMethods
U OBJC_METACLASS$_NSObject
U ___CFConstantStringClassReference
U __objc_empty_cache
0000000000000c90 T _hello
0000000000000cb0 T _mouseMove
U _sleep
U dyld_stub_binder

Don’t use underscores in method names — they get translated into colons in ASObjC. You should also end your calls to methods in ().

That fixed it - thanks so much !!

One thing that threw me was the behaviour of fsTrue from the FScript.framework. It seems to happily be called as fsTrue (without appending a parenthesis suffix) - but it also works with the suffix. Also, I think i made many false conclusions when I failed to quit and relaunch Script Debugger in order to clear out cached file references to a ‘deleted’ and replaced framework.

When you leave off the parentheses, key-value coding is used; when you include them, the bridge uses the method signature to decide how to translate results. Sometimes the result is the same, but not always.

[quote=“herheque, post:5, topic:2925”] to clear out cached file references to a ‘deleted’ and replaced framework
[/quote]

That’s nothing to do with file references — it’s simply that once a framework is loaded, it can’t be unloaded.