Scott Babcock wrote:
I have a bunch of library functions implemented in AppleScript. This is really great for providing common functionality to code written in AppleScript, but these functions aren't available to code written in other languages. Is there any way to wrap this library suite in such a way as to expose an Apple Event interface that can be used by code written in other languages (C, Python, Ruby, etc.)?
I know that AppleScript Studio provides a method for AppleScript code to access Cocoa functionality, but I need to turn this on its head - to provide access to AppleScript functionality from Obj-C. I'd need to define my terminology in the traditional way in my AppleScript Studio application, but then I'd need some way to connect the terminology to the implementation.
The AppleScriptKit framework doesn't provide a way for ObjC code to get hold of the script object instances that contain a Studio-based app's internal state, so Studio isn't any help here.
If you want to give your application a proper looking dictionary, you could create a pure ObjC application that installs its own event handlers via NSAppleEventManager (simplest) and forwards the incoming events to an NSAppleScript instance containing your AppleScript handlers. Although unless you're primarily doing this for benefit of AppleScript users (who like a nice keyword-based command syntax), that's really just giving yourself extra work for no real benefit, since Python, Ruby, etc. already use conventional function call syntax anyway.
You could also use NSAppleScript (either directly from ObjC or via PyObjC/RubyCocoa) to load up your script and call its handlers within your existing process. It does mean lots of tedious mucking about with NSAppleEventDescriptors to pack and unpack events used by -executeAppleEvent:error:, although you could use objc-appscript's AEMCodecs class to take care of that for you; there's a sample Xcode project in [objc-]appscript's svn repository that shows how. (I can also recall seeing one or two third-party alternatives to NSAppleScript that may provide some type conversion support, although I'm not sure if they're still actively maintained.) And if you really need to use C, there's always the original Carbon OSA API which is even more tedious to deal with but will do the job.
Personally, I'd just do the simplest thing possible, which is to define your AppleScript handlers with user-defined identifiers as names and positional-only parameters and save your AppleScript as a stay-open applet which will provide the event handling side for you. You can then write yourself some minimal Python/Ruby/C libraries to call the applet's handlers from another process in reasonable comfort, e.g. using Python + appscript:
### TestApplet.app ###
on someHandler(x, y, z) return x + y * z end someHandler
### test.py ###
import aem
class Applet: def __init__(self, appname): self._app = aem.Application(aem.findapp.byname(appname))
def call(self, name, *args): return self._app.event('ascrpsbr', {'snam': name, '----': args}).send()
# TEST
print Applet('TestApplet').call('somehandler', 1, 2, 3) #-> 7
You can even pretty the syntax up by using Python's __getattr__/Ruby's #method_missing methods to let you write your calls as:
print Applet('TestApplet').somehandler(1, 2, 3)
Although that's left as an exercise for the reader as it does require awareness of the gotchas involved with using this sort of runtime magic.
BTW, remember that AppleScript identifiers are case-insensitive by default, so use all-lowercase names when calling handlers unless the original handler name is written in pipes, in which case it's case-sensitive.
...
One last consideration: AppleScript is great for controlling other applications, but really sucks for anything else. Therefore, creating an AppleScript library for use by other languages is probably worth doing if your handlers are providing lots of intensive application automation-related functionality that would be a lot of work to port. OTOH, if it's just a lot of general-purpose functionality (e.g. text, math, XML, database, internet, etc, etc.), other languages will almost certainly already have much better native libraries available for such tasks and you should really go use those instead.
HTH
has -- Control AppleScriptable applications from Python, Ruby and ObjC: http://appscript.sourceforge.net
|