Recent

Author Topic: Incompatible type for arg... address of function.... is nested  (Read 1387 times)

440bx

  • Hero Member
  • *****
  • Posts: 1198
Hello,

I am porting some Delphi 2 code which compiles and runs fine (that is, on the platform it was built to run on.)  I am getting the following error from FPC:

Code: Pascal  [Select]
  1. (5089,66) Error: Incompatible type for arg no. 2: Got "<address of function(LongInt;LongInt;LongInt):LongInt is nested;StdCall>", expected "<procedure variable type of function(LongInt;LongInt;LongInt):LongInt;StdCall>"
the parameter types and result all seem fine but, the message has "is nested" after the function result.

The function isn't nested into another function or procedure.  It's a normal function. 

What is the meaning of "is nested" and what am I supposed to change to make it acceptable to FPC ?

just in case it helps, the error takes place on the line that calls SetWindowsHookEx:
Code: Pascal  [Select]
  1.       case Captured of
  2.         TRUE:
  3.           begin
  4.             Scroll32Hook := SetWindowsHookEx(WH_MSGFILTER,
  5.                                              @ScrollHookMsgFilter,
  6.                                              0,                  { local hook }
  7.                                              GetCurrentThreadId);
  8.           end;
  9.  
  10.         FALSE:
  11.           begin
  12.             if Scroll32Hook <> 0 then UnhookWindowsHookEx(Scroll32Hook);
  13.             Scroll32Hook := 0;
  14.           end;
  15.       end; { case Captured }
  16.  

the hook function is:

Code: Pascal  [Select]
  1. function ScrollHookMsgFilter(Code   : longint;
  2.                              wParam : ptrint;
  3.                              Msg    : ptrint) : ptrint; stdcall;
  4. var
  5.   MsgPtr     : PMsg absolute Msg;
  6.   BoxInfoPtr : PBoxInfo;
  7.  
  8. begin
  9.   BoxInfoPtr := pointer(GetWindowLong(GetCapture, 0));
  10.  
  11.   with BoxInfoPtr^, MsgPtr^ do
  12.     begin
  13.       Scroll32PosB := Pt;
  14.       ScreenToClient(hWnd, Scroll32PosB);
  15.     end;
  16.  
  17.   Result := 0;
  18. end;
  19.  

NOTE: I'm currently porting it to FPC in 32bit.  I am not yet focusing on changing the data types and function calls to make it runnable in 64bit (e.g, GetWindowLong to GetWindowLongPtr, etc.)

Thank you for your help.
using FPC v3.0.4 and Lazarus 1.8.2 on Windows 7 64bit.

marcov

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 7503
Re: Incompatible type for arg... address of function.... is nested
« Reply #1 on: March 12, 2019, 10:06:47 pm »
Nested procvars are a separate type of proc/methods vars.

So you have normal procedures variables for global functions, procedure "of object" for methods, and "is nested" for nested functions.

Nested functions are a bit like method vars, in that the procvars are two pointers and have limited validity.

  • method vars contain code: function address and data :self, and validity till the object is freed.
  • nested procvar contain code: function address and data: framepointer, and validity till the outer procedure is finished and the framepointer is thus no longer valid

In short, it is is a fairly pascal specific feature, and I doubt it will be of use in windows interfacing. I suspect you are accidentally trying to passa nested function to something expecting a global function, and you are not in {$mode delphi}

jamie

  • Hero Member
  • *****
  • Posts: 2083
Re: Incompatible type for arg... address of function.... is nested
« Reply #2 on: March 12, 2019, 10:12:10 pm »
Code: Pascal  [Select]
  1. function SetWindowsHookEx(idHook:longint; lpfn:HOOKPROC; hmod:HINST; dwThreadId:DWORD):HHOOK;
  2.  

Try Casting around your address of your callback...

 HOCKRPOC(@YourcallBack)
Number 1 at blue screen app creations!

440bx

  • Hero Member
  • *****
  • Posts: 1198
Re: Incompatible type for arg... address of function.... is nested
« Reply #3 on: March 12, 2019, 10:27:27 pm »
Nested procvars are a separate type of proc/methods vars.

So you have normal procedures variables for global functions, procedure "of object" for methods, and "is nested" for nested functions.

Nested functions are a bit like method vars, in that the procvars are two pointers and have limited validity.

  • method vars contain code: function address and data :self, and validity till the object is freed.
  • nested procvar contain code: function address and data: framepointer, and validity till the outer procedure is finished and the framepointer is thus no longer valid

In short, it is is a fairly pascal specific feature, and I doubt it will be of use in windows interfacing. I suspect you are accidentally trying to passa nested function to something expecting a global function, and you are not in {$mode delphi}

@Marco

The thing is, the function is not a method, and is not nested.  It's just a plain vanilla function.  Nothing special about it other than being called by a hook.   I am not in {$MODE DELPHI}, I haven't needed it to specify callbacks in other cases (such as the examples I've given in the bug tracker for various enumeration APIs, none have required {$MODE DELPHI}.)

Maybe there is something in the code that makes it believe the function is nested into another.  I'll double check the code.

@Jamie
Try Casting around your address of your callback...

 HOCKRPOC(@YourcallBack)

Thank you Jamie, that works.  I don't see why I have to cast it but, for now, I'll take it.  I'm sure that's going to bite me later but, at least for now, I can move forward.

There must be something in the code that is confusing FPC.  It will be interesting to find out what it is.
using FPC v3.0.4 and Lazarus 1.8.2 on Windows 7 64bit.

Remy Lebeau

  • Hero Member
  • *****
  • Posts: 675
    • Lebeau Software
Re: Incompatible type for arg... address of function.... is nested
« Reply #4 on: March 13, 2019, 12:24:27 am »
The thing is, the function is not a method, and is not nested.  It's just a plain vanilla function.
...
There must be something in the code that is confusing FPC.  It will be interesting to find out what it is.

Kind of hard to judge that when you did not show the full code.
Remy Lebeau
Lebeau Software - Owner, Developer
Internet Direct (Indy) - Admin, Developer (Support forum)

440bx

  • Hero Member
  • *****
  • Posts: 1198
Re: Incompatible type for arg... address of function.... is nested
« Reply #5 on: March 13, 2019, 01:42:22 am »
The thing is, the function is not a method, and is not nested.  It's just a plain vanilla function.
...
There must be something in the code that is confusing FPC.  It will be interesting to find out what it is.

Kind of hard to judge that when you did not show the full code.
I know but, the unit is almost 6000 lines and in the middle of being edited for porting. 

I should have probably mentioned that I figured out what the problem was.  Kind of hard to explain how thing that got there but, in the midst of conditional directives and definitions, there was an unmatched brace.  It didn't bother Delphi but, it somehow ended up  creating a partial definition for a function and FPC saw the whole remainder of the program as being part of the function.

What helped me figure it out is that, once I had eliminated all the other syntactic details FPC didn't like and, it got to the end of the unit, it complained that it expected a semicolon and not a period after the "end" (the "end." that marked the unit's end). 

The compiler was telling the truth, it was seeing a whole slew of functions and procedures inside another one and complained that the function was not properly terminated (with an "end;".) 

Remy, thank you for trying to help, I appreciate it.
using FPC v3.0.4 and Lazarus 1.8.2 on Windows 7 64bit.

Remy Lebeau

  • Hero Member
  • *****
  • Posts: 675
    • Lebeau Software
Re: Incompatible type for arg... address of function.... is nested
« Reply #6 on: March 13, 2019, 02:42:37 am »
in the midst of conditional directives and definitions, there was an unmatched brace.  It didn't bother Delphi

Delphi allows you to take the address of a nested function, such as for use as an API callback, but it is not safe/recommended to do so because of the tricks the compiler has to play with the stack frames to allow nested functions to access local variables of outer frames.  I guess FreePascal is more restrictive about using the address of nested functions in function pointers.
Remy Lebeau
Lebeau Software - Owner, Developer
Internet Direct (Indy) - Admin, Developer (Support forum)

440bx

  • Hero Member
  • *****
  • Posts: 1198
Re: Incompatible type for arg... address of function.... is nested
« Reply #7 on: March 13, 2019, 04:05:24 am »
Delphi allows you to take the address of a nested function, such as for use as an API callback, but it is not safe/recommended to do so because of the tricks the compiler has to play with the stack frames to allow nested functions to access local variables of outer frames.  I guess FreePascal is more restrictive about using the address of nested functions in function pointers.
What happened is that, because Delphi and FPC don't treat nested comments the same way (using braces), Delphi was seeing the code as I meant it to be.  For FPC it resulted in a "lone" function header which gobbled up the entire rest of the unit.  I didn't realize that until I had corrected all the other things that Delphi was ok with but FPC objected to.

Once the code was syntactically acceptable to FPC then it complained about expecting a semicolon instead of a period and then it was also possible to see some warnings about nested comments.  The combination of the error and the warning messages was enough to find where the culprit misplaced brace was.

This is the second time a misplaced brace gives me a headache.  Never noticed them before because Delphi doesn't do nested comments.

using FPC v3.0.4 and Lazarus 1.8.2 on Windows 7 64bit.

Thaddy

  • Hero Member
  • *****
  • Posts: 9177
Re: Incompatible type for arg... address of function.... is nested
« Reply #8 on: March 13, 2019, 07:41:03 am »

This is the second time a misplaced brace gives me a headache.  Never noticed them before because Delphi doesn't do nested comments.
And you can do the same in FPC because you can switch them off (default in $mode delphi)

Some people never read documentation.... https://www.freepascal.org/docs-html/current/prog/progsu105.html#x113-1140001.3.22 which is rather annoying especially if it is  someone who likes to switch anything useless or useful anyway.
Code: Pascal  [Select]
  1. {$modeswitch nestedcomments-}
« Last Edit: March 13, 2019, 07:54:05 am by Thaddy »
also related to equus asinus.

440bx

  • Hero Member
  • *****
  • Posts: 1198
Re: Incompatible type for arg... address of function.... is nested
« Reply #9 on: March 13, 2019, 07:57:17 am »

This is the second time a misplaced brace gives me a headache.  Never noticed them before because Delphi doesn't do nested comments.
And you can do the same in FPC because you can switch them off (default in $mode delphi)

Some people never read documentation....
one directive I would gladly use is {$thaddy off} but it's not documented and, I'm pretty sure it wouldn't work anyway.
using FPC v3.0.4 and Lazarus 1.8.2 on Windows 7 64bit.

Thaddy

  • Hero Member
  • *****
  • Posts: 9177
Re: Incompatible type for arg... address of function.... is nested
« Reply #10 on: March 13, 2019, 10:29:05 am »
one directive I would gladly use is {$thaddy off}
I would be proud of that! When I am dead... Still you'd be better off to actually read the documentation. Which is excellent. Which you refuse to do.... Which in turn is completely silly.

The documentation is extremely good.
« Last Edit: March 13, 2019, 10:33:45 am by Thaddy »
also related to equus asinus.