Recent

Author Topic: [SOLVED] Objective-Pascal incorrect code gets "unrecognized selector"crash.  (Read 2463 times)

lor

  • New Member
  • *
  • Posts: 26
Lazarus 1.2.6  FPC 2.6.4   i386-darwin-carbon

Problem with a unit implemented with Objective-Pascal. This is my first Lazarus Objective-Pascal, although I have significant experience with FPC Pascal and separately with Xcode on Mac OSX.

It seems I don't understand something. Having studied online documentation including "FPC PasCocoa", "Cocoa Interface", and "FPC PasCocoa/Differences", I'm still somewhat confused as to the proper code to accomplish the interface to the Objective-C system. You can see my code (relevant parts) below the extracts from the crash reports seen next.

I tried with both the class method NSData dataWithBytes:: and with the instance method initWithBytes:: (both codes below, one commented out) and they both result in somewhat similar crashes as given below.

Any comments are greatly appreciated.  Thank you.


/======== crash report for dataWithBytes ========

Exception Type:  EXC_BREAKPOINT (SIGTRAP)
Exception Codes: 0x0000000000000002, 0x0000000000000000

External Modification Warnings:
Debugger attached to process.

Application Specific Information:
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '+[NSData dataWithBytes::]: unrecognized selector sent to class 0xac41fe5c'

Application Specific Backtrace 1:
0   CoreFoundation                      0x93ab3e8b __raiseError + 219
1   libobjc.A.dylib                     0x9947652e objc_exception_throw + 230
2   CoreFoundation                      0x93ab78ed +[NSObject(NSObject) doesNotRecognizeSelector:] + 253
3   CoreFoundation                      0x939ffe87 ___forwarding___ + 487
4   CoreFoundation                      0x939ffc32 _CF_forwarding_prep_0 + 50
5   MORSEDI                             0x00379210 LORSONUS_TESTSOUND_1$ANSISTRING$LONGINT$ANSISTRING$$BOOLEAN + 144
6   MORSEDI                             0x0004db99 UNIT1_STARTFORM1 + 1481
7   MORSEDI                             0x00049c1b UNIT1_TFORM1_$__CREATE$TCOMPONENT$$TFORM1 + 123
8   MORSEDI                             0x000467f0 FORMS_TAPPLICATION_$__CREATEFORM$TCOMPONENTCLASS$formal + 144
9   MORSEDI                             0x0001127e PASCALMAIN + 78
10  MORSEDI                             0x0002f2e6 FPC_SYSTEMMAIN + 70
11  MORSEDI                             0x000111e8 _start + 207
12  MORSEDI                             0x00011118 start + 40

========/

/======== crash report for initWithBytes ========

Application Specific Information:
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[NSConcreteData initWithBytes::]: unrecognized selector sent to instance 0x38e1d90'

Application Specific Backtrace 1:
0   CoreFoundation                      0x93ab3e8b __raiseError + 219
1   libobjc.A.dylib                     0x9947652e objc_exception_throw + 230
2   CoreFoundation                      0x93ab7afd -[NSObject(NSObject) doesNotRecognizeSelector:] + 253
3   CoreFoundation                      0x939ffe87 ___forwarding___ + 487
4   CoreFoundation                      0x939ffc32 _CF_forwarding_prep_0 + 50
5   MORSEDI                             0x00379212 LORSONUS_TESTSOUND_1$ANSISTRING$LONGINT$ANSISTRING$$BOOLEAN + 178
6   MORSEDI                             0x0004db79 UNIT1_STARTFORM1 + 1481
7   MORSEDI                             0x00049bfb UNIT1_TFORM1_$__CREATE$TCOMPONENT$$TFORM1 + 123
8   MORSEDI                             0x000467d0 FORMS_TAPPLICATION_$__CREATEFORM$TCOMPONENTCLASS$formal + 144
9   MORSEDI                             0x0001125e PASCALMAIN + 78
10  MORSEDI                             0x0002f2c6 FPC_SYSTEMMAIN + 70
11  MORSEDI                             0x000111c8 _start + 207
12  MORSEDI                             0x000110f8 start + 40

========/

/======== relevant code ========

unit LORsonus;

{$mode objfpc}
{$modeswitch objectivec2}
{$H+}

interface

{$linkframework Foundation}
{$linkframework CoreFoundation}
{$linkframework AppKit}
{$linkframework AVFoundation}

function TestSound_1(var soundstream :ansistring; soundsize :longint; var sounderror :ansistring) :boolean;

implementation

uses
    Classes, SysUtils;

type
    TNSData = objcclass external name 'NSData' (NSObject)
    public
    class function dataWithBytes(sounddata :pointer; soundsize :longint) :TNSData; message 'dataWithBytes::';
    function initWithBytes(sounddata :pointer; soundsize :longint) :TNSData; message 'initWithBytes::';
end;

var
    SonusData   :TNSData;

function ansistrptr (var A :ansistring) :pointer;
begin
     ansistrptr := @A[1];
end;

function TestSound_1(var soundstream :ansistring; soundsize :longint; var sounderror :ansistring) :boolean;
var  tstsoundstream :ansistring = 'test string';
begin

    {SonusData := TNSData.alloc;}
    {SonusData := SonusData.initWithBytes(ansistrptr(tstsoundstream), soundsize);}
    {vs...Tried above and below with similar result of unrecognized selector}
    SonusData := TNSData.dataWithBytes(ansistrptr(tstsoundstream), soundsize);

    if SonusData = nil then
        sounderror := 'SonusData did not initialize.' else sounderror := '';
    TestSound_1 := (SonusData <> nil);
end;

========/

/======== Copied from NSData Class Reference ========

+ dataWithBytes:length:

Creates and returns a data object containing a given number of bytes copied from a given buffer.

Declaration
OBJECTIVE-C
+ (instancetype)dataWithBytes:(const void *)bytes
                       length:(NSUInteger)length
Parameters
bytes   A buffer containing data for the new object.
length   The number of bytes to copy from bytes. This value must not exceed the length of bytes.

Return Value
A data object containing length bytes copied from the buffer bytes. Returns nil if the data object could not be created.

Import Statement
OBJECTIVE-C
@import Foundation;

========/
« Last Edit: March 14, 2015, 04:37:49 pm by lor »

Jonas Maebe

  • Hero Member
  • *****
  • Posts: 669
Re: Objective-Pascal incorrect code gets "unrecognized selector"crash.
« Reply #1 on: March 14, 2015, 02:59:58 pm »
Your selector is indeed wrong. The selector name of "+ (instancetype)dataWithBytes:(const void *)bytes length:(NSUInteger)length" is 'dataWithBytes:length:'. That's unrelated to Objective-Pascal specifically, it's how message names are defined in Objective-C.

lor

  • New Member
  • *
  • Posts: 26
Re: Objective-Pascal incorrect code gets "unrecognized selector"crash.
« Reply #2 on: March 14, 2015, 04:05:30 pm »
I believe you are  saying my 'message' specifiers need to include the 'length:' part of the selector, indeed all additional parameters?  I shall now try that.  I had somehow assumed only the method name was needed in the message. None of the examples I found in the online documentation had anything else, but then those examples didn't require any such.  Thanks so very much. I knew I was very close to success. 'The devil is in the details.'

Jonas Maebe

  • Hero Member
  • *****
  • Posts: 669
Re: Objective-Pascal incorrect code gets "unrecognized selector"crash.
« Reply #3 on: March 14, 2015, 04:07:35 pm »
"length:" is not a parameter, it's part of the message name itself. The "(NSUInteger)length" at the end is the parameter.

lor

  • New Member
  • *
  • Posts: 26
Yes, I guess I should have said "...indeed the message components representing all of the additional parameters" or something to that effect.  In any case, you have solved my problem. Many thanks again.