Space Vatican

Ramblings of a curious coder

NSData and RubyCocoa on 10.7

For some reason code like

1
OSX::NSData.dataWithBytes_length(data, data.length)

segfaults on lion. Others have noted that this only occurs when the data contains bytes with the high bit set. This smells like something trying to interpret the string in some encoding when the string is in fact arbitrary binary data.

I’d love to use MacRuby instead of RubyCocoa, but unfortunately MacRuby doesn’t seem to be able to handle Active Record at the moment, so I can’t use it (yet). I haven’t had time to delve properly into how RubyCocoa converts between ruby and Objective-C objects but I was able to hack around by using ruby inline

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
require 'inline'
class CFDataGenerator
  begin
    inline do |builder|
      builder.include "<CoreFoundation/CoreFoundation.h>"
      builder.c_raw_singleton "
      
      static VALUE from_string(int argc, VALUE *args){
        CFDataRef d = CFDataCreate(NULL, RSTRING_PTR(args[0]), RSTRING_LEN(args[0]));    
        
        VALUE result;
        char type = '@';
        ocdata_to_rbobj(Qnil,&type, (const void *)&d, &result, false) ;
        return result;
      }
    "
    end
  end
end

Then you can use CFDataGenerator.from_string to convert ruby strings into nsdata instances. Remember to release the instance when you’re done!