Cocoa AppleEvents problem

I and another app (XCode-based) vender have created an API for passing information between our apps. I’ve been sending back a string that contains both hex values and text, and it worked will until Cocoa. Now if I send back values with a byte >= 128 he’s receiving 0’s. For example, I send back the 4 bytes

00 00 00 80

to indicate 128 items, and he’s seeing zeros.

I’m guessing that this has something to do with a fix in Cocoa that has AE now working correctly with UTF8-encoded string.

I’ve tried working around this by encoding the string as ASCII, but so far that’s not working.

I know there are other solutions to returning complex data (mixed binary and text) and I may have to resort to that. However, it will break all our existing users apps (there are many thousands of users), so I’d much prefer to keep the old solution.

Joe, can you explain what the problem is, and if there is any workaround (I though encoding as ASCII would do the trick, but so far no luck). Thanks.

How are you crafting this data to send ?
Are you using Chr or ChrB ?

I’m creating a string object in Xojo. It’s a mixture of binary data (that I add using cur() or asc()) and RTF. I define the string as UTF8 (if I don’t, the calling app receives nothing).

In general, all strings get converted to UTF-16 before sending, even if don’t have a defined encoding (i.e. a bucket of bytes). The expectation is that if you’re using any of the ‘String’-related methods, you’re dealing with text. The old code made a similar assumption, just that it always used typeChar instead of typeUnicode.

It’d seem like the AppleEvent classes should get ‘Data’ variants if you intend on sending raw data or that it should treat strings without a defined encoding as data. The latter potentially gets tricky when you need to deal with the getters, though I don’t recall all of the details. I’d recommend you file a feature request or bug report, depending on your feelings on the matter.

As for a workaround, if you could tell me exactly what class and method you’re calling, I can tell you what declare you’ll need.

I’m using the ae.send Xojo method:

ae.stringParam("----") = s
ae.timeout = 2
call ae.send

[quote=15834:@Jonathan Ashwell]I’m using the ae.send Xojo method:

ae.stringParam("----") = s
ae.timeout = 2
call ae.send[/quote]

Okay, you can get the AppleEvent object’s underlying AppleEvent and use declares with it. Here’s a bit of untested code that should work:

[code] Declare Function AEPutParamPtr Lib “CoreServices” ( theAppleEvent As Integer, theAEKeyword As OSType, _
typeCode As OSType, dataPtr As Ptr, dataSize As Integer ) As Integer
const keyDirectObject = “----”
const typeChar = “TEXT”

dim data as MemoryBlock = // ...
dim theEvent as AppleEvent = // ...
dim err as integer = AEPutParamPtr( theEvent.Ptr, keyDirectObject, typeChar, data, data.size )
// ...[/code]

You may want to choose a better type than typeChar, but that’d give you essentially what you were getting under Carbon.

It’s not working, and unfortunately I’ll have to make a build and ask my colleague what he’s receiving. Here’s the actual code I’m using

Declare Function AEPutParamPtr Lib "CoreServices" ( theAppleEvent As Integer, theAEKeyword As OSType, _
typeCode As OSType, dataPtr As Ptr, dataSize As Integer ) As Integer
const keyDirectObject = "----"
const typeChar = "TEXT"

dim data as MemoryBlock= s
dim theEvent as AppleEvent = NewAppleEvent("mLeL", "SCNR", "mLeL")
dim err as integer = AEPutParamPtr( theEvent.Ptr, keyDirectObject, typeChar, data, data.size )

The event is sent (err = 0).

I’ll find out what he’s receiving and get back. Thanks a lot.

Followup. In Carbon builds I had to define the string I was sending as UTF8 to get the ae.send to work. Now I find that this was the problem – for some reason the bytes received at the other end were not correct (I’m waiting to get the actual data received). But now in Cocoa if I set the string encoding (of this bucket of bytes) to nil, it works again. Odd but (apparently) true. Thanks for your help, Joe.

I’d still like to understand this a bit better. You can get a log of AppleEvent sends by opening Terminal, setting the AEDebugSends environment variable to 1, and then launching your application via the full executable path. For example:
AEDebugSends=1 /Applications/Real\ Studio\ 2012r2.1.app/Contents/MacOS/Real\ Studio

If you can send me the output of that with your application built with Carbon and Cocoa, I’d appreciate it.

I don’t know if this will be of much help, but here are the console logs (I did each condition twice). The first 2 examples are Cocoa with the string encoding set to UTF8 (which does not work):

aevt(‘mLeL’\‘SCNR’ transactionID=0 returnID=25853 sourcePSN=‘sign’(364C654C6D36) timeout=120 eventSource=3 { ‘----’:TEXT("") })
aevt(‘mLeL’\‘SCNR’ transactionID=0 returnID=21431 sourcePSN=‘sign’(364C654C6D36) timeout=120 eventSource=3 { ‘----’:TEXT("") })

These 2 examples are with the string encoding set to nil (this works):

aevt(‘mLeL’\‘SCNR’ transactionID=0 sourcePSN=‘sign’(364C654C6D36) timeout=120 eventSource=3 { ‘----’:TEXT("") })
aevt(‘mLeL’\‘SCNR’ transactionID=0 returnID=14149 sourcePSN=‘sign’(364C654C6D36) timeout=120 eventSource=3 { ‘----’:TEXT("") })

[quote=15957:@Jonathan Ashwell]I don’t know if this will be of much help, but here are the console logs (I did each condition twice). The first 2 examples are Cocoa with the string encoding set to UTF8 (which does not work):

aevt(‘mLeL’\‘SCNR’ transactionID=0 returnID=25853 sourcePSN=‘sign’(364C654C6D36) timeout=120 eventSource=3 { ‘----’:TEXT("") })
aevt(‘mLeL’\‘SCNR’ transactionID=0 returnID=21431 sourcePSN=‘sign’(364C654C6D36) timeout=120 eventSource=3 { ‘----’:TEXT("") })

These 2 examples are with the string encoding set to nil (this works):

aevt(‘mLeL’\‘SCNR’ transactionID=0 sourcePSN=‘sign’(364C654C6D36) timeout=120 eventSource=3 { ‘----’:TEXT("") })
aevt(‘mLeL’\‘SCNR’ transactionID=0 returnID=14149 sourcePSN=‘sign’(364C654C6D36) timeout=120 eventSource=3 { ‘----’:TEXT("") })[/quote]

That’s odd, I would expect ‘utxt’ for the Cocoa one and not TEXT. What happens if you send actual Unicode text? Or is this when using your declare?

This is just using ae.send. The only difference is that in the first case the encoding was nil. In the second the encoding was UTF8. The data is a mixture of arbitrary bytes and UTF8 characters (actually RTF, so all are <= ASCII 127).