Recent

Author Topic: Lazarus vs Delphi pointers  (Read 3716 times)

morknot

  • New Member
  • *
  • Posts: 45
  • still learning
Lazarus vs Delphi pointers
« on: January 14, 2019, 03:39:10 pm »
I am converting an old Delphi application to Lazarus. All has gone well until I had to start dealing with pointers in one unit. The unit works in Delphi mode {$MODE Delphi} but I would like it to work in {$mode objfpc}{$H+} mode. The application uses Windows MMSystem and :

TMidiHdr = record
    lpData: pchar;                 { pointer to locked data block }
    dwBufferLength: Longint;       { length of data in data block }
    dwBytesRecorded: Longint;      { used for input only }
    dwUser: Longint;               { for client's use }
    dwFlags: Longint;              { assorted flags (see defines) }
    lpNext: PMidiHdr;              { reserved for driver }
    reserved: Longint;             { reserved for driver }



and

midioutprepareheader(HMIDIOOUT hmo, LPMIDIHDR lpMidiOutHdr, UINT cbMidiOutHdr)


The following works fine

Code: Pascal  [Select][+][-]
  1.  
  2. unit sysex;
  3.  
  4. {$MODE Delphi}
  5.  
  6. interface
  7.  
  8. uses MMSystem…..;
  9.  
  10. type
  11.   PMidiHdr = ^TMidiHdr;    
  12.  
  13. procedure SendSysex(sysexdata:string);
  14.  
  15.  implementation
  16.  
  17.  
  18. procedure SendSysex(sysexdata:string);
  19. var
  20. midih:PMidiHdr;
  21. rc:integer;
  22. Psysex:^Pchar;
  23.  
  24. begin
  25.  
  26.  
  27. //sysexdata is in the form #$F0#$00#$F7.....
  28.  
  29.  
  30. //lphmo is the address of a handle
  31.  
  32. Psysex:=@sysexdata;
  33.  
  34. new(midih);
  35.  
  36. GetMem(midih.lpData, length(sysexdata)+1);
  37.  
  38. StrMove(midih.lpData, Psysex^, length(sysexdata)+1);
  39.  
  40. midih^.dwBufferLength := length(sysexdata);
  41.  
  42. midih^.dwFlags := 0;
  43.  
  44. rc := midiOutPrepareHeader(lphmo, @midih.lpData, sizeof(Tmidihdr));
  45. If rc<>0 then ShowMessage('Header Not Prepared');
  46.  
  47. rc := midiOutLongMsg(lphmo, @midih.lpData, sizeof(Tmidihdr));
  48. IF rc<>0 then Showmessage('Sysex Data Not Sent');
  49. rc := midiOutUnprepareHeader(lphmo, @midih.lpData, sizeof(Tmidihdr));
  50.  
  51.  
  52. FreeMem(midih.lpData);
  53. dispose(midih);
  54. sysexdata:='';
  55. end;
  56.            
  57.  

I have tried many changes to get the above to work under FPC mode but always get the error "may be pointer derefence is missing" and Fatal: Syntax error, ")" expected but "identifier LPDATA" found.


I would be grateful if someone could explain what the problem is. Thanks
     

Blaazen

  • Hero Member
  • *****
  • Posts: 3241
  • POKE 54296,15
    • Eye-Candy Controls
Lazarus 2.3.0 (rev main-2_3-2863...) FPC 3.3.1 x86_64-linux-qt Chakra, Qt 4.8.7/5.13.2, Plasma 5.17.3
Lazarus 1.8.2 r57369 FPC 3.0.4 i386-win32-win32/win64 Wine 3.21

Try Eye-Candy Controls: https://sourceforge.net/projects/eccontrols/files/

lucamar

  • Hero Member
  • *****
  • Posts: 4219
Re: Lazarus vs Delphi pointers
« Reply #2 on: January 14, 2019, 05:16:44 pm »
Other notes:
  • With Psysex:^Pchar you're creating a pointer to a pointer to char but LPData is a pointer to char
  • AnsiString (the default string in $H+ mode) is really a pointer so to make a pointer to the string chars you need to make it point to the first char: Psysex:=@(sysexdata[1])
    or maybe use a hard cast: Psysex := PChar(sysexdata)
Turbo Pascal 3 CP/M - Amstrad PCW 8256 (512 KB !!!) :P
Lazarus/FPC 2.0.8/3.0.4 & 2.0.12/3.2.0 - 32/64 bits on:
(K|L|X)Ubuntu 12..18, Windows XP, 7, 10 and various DOSes.

morknot

  • New Member
  • *
  • Posts: 45
  • still learning
Re: Lazarus vs Delphi pointers
« Reply #3 on: January 15, 2019, 03:14:13 pm »
Thank you for your help and suggestions, Blaazen and lucamar. I will continue to experiment.

Thaddy

  • Hero Member
  • *****
  • Posts: 14393
  • Sensorship about opinions does not belong here.
Re: Lazarus vs Delphi pointers
« Reply #4 on: January 15, 2019, 03:30:53 pm »
You should stick to the original code and not change anything. That way it is far easier to debug for us.
I expect it is a very simple fix because everything points to a windows api declaration.
And those are not always compatible between FPC and Delphi for several reasons.
This is not a language dialect issue: if we have a good example it should compile both ways.

Also note that the Delphi versions of the Windows API units contain many mistakes (missing ; etc) that can cause your issue.
E.g.: I had to correct a lot for KOL but FPC is really near 100% compatible to D7. Even D2007.

So if that code does not compile, focus on your existing code and show us where it fails.
« Last Edit: January 15, 2019, 03:35:59 pm by Thaddy »
Object Pascal programmers should get rid of their "component fetish" especially with the non-visuals.

morknot

  • New Member
  • *
  • Posts: 45
  • still learning
Re: Lazarus vs Delphi pointers
« Reply #5 on: January 16, 2019, 10:46:22 am »
Thank you for your reply, Thaddy.

If I compile the above code with {$mode objfpc}{$H+} then the compilation fails at

GetMem(midih.lpData,length(sysexdata)+1);

with the errors for midih.lpdata as:

 Error: Illegal qualifier
 Hint: may be pointer dereference is missing
 Fatal: Syntax error, ")" expected but "identifier LPDATA" found

If I change the parameter to midih^.lpdata for both the GetMem and StrMove statements then the compilation fails at

rc := midiOutPrepareHeader(lphmo, @midih.lpData, sizeof(Tmidihdr)); with the same errors.

When I change the second parameter to just @midi for this and the next two statements and
the FreeMem parameter to just midih there are no compilation errors and rc=0 as required but an 'External: SIGSEGV error occurs when the sysexdata string is changed.


I hope this is enough info. Thanks again.




marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 11459
  • FPC developer.
Re: Lazarus vs Delphi pointers
« Reply #6 on: January 16, 2019, 10:51:14 am »
use midih^.lpdata

Mode objfpc doesn't autoderef. (though I would keep everything just mode delphi, there is nothing wrong with it)

morknot

  • New Member
  • *
  • Posts: 45
  • still learning
Re: Lazarus vs Delphi pointers
« Reply #7 on: January 16, 2019, 11:40:12 am »
Thank you for your reply Marcov. If I have understood you, when I use midi^.lpdata for the midiOutPrepareHeader statement then the compile fails with

Error: Incompatible type for arg no. 2: Got "PChar", expected "LPMIDIHDR"

I did want to try and understand the differences between FPC and DelphI but think you are right, I will just stick with mode Delphi.


 

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 11459
  • FPC developer.
Re: Lazarus vs Delphi pointers
« Reply #8 on: January 16, 2019, 11:52:06 am »
Yes, that is another difference. In Delphi pchar is special in conversions (clearly seen that p
  • worked before D2009, while that worked on no other pointer type). pchar strings are often used as buffer types, and therefore less typechecked. FPC modes are more strict.


No way out for that but typecasting to the right pointer type.

 

TinyPortal © 2005-2018