X# error XS9052 (In .Net you cannot take the address of a method or a function)

This forum is meant for questions and discussions about the X# language and tools
Post Reply
User avatar
Kees Bouw
Posts: 119
Joined: Wed Nov 06, 2019 11:35 am
Location: Netherlands

X# error XS9052 (In .Net you cannot take the address of a method or a function)

Post by Kees Bouw »

Hello everyone,

The VO app that I am converting to X# has the following code:

Code: Select all

_DLL FUNCTION EnumFontFamiliesEx(hDC AS PTR, lpLogFont AS _winLOGFONT, lpEnumFontFamExProc AS PTR, lParam AS DWORD, dwFlags AS DWORD) AS DWORD PASCAL:GDI32.EnumFontFamiliesExA
and

Code: Select all

FUNCTION EnumFontFamExProc(lpelfe AS _winENUMLOGFONTEX, lpntme AS _winNEWTEXTMETRICEX, FontType AS DWORD, lParam AS LONG) AS INT CALLBACK

AAdd(aFontFamilies, {Psz2String(@lpelfe.elfFullName), Psz2String(@lpelfe.elfStyle), Psz2String(@lpelfe.elfScript)})

RETURN 1
and

Code: Select all

LOCAL struLF IS _winLOGFONT

struLF.lfCharSet := DEFAULT_CHARSET

EnumFontFamiliesEx(GetDC(SELF:Handle()), @struLF, @EnumFontFamExProc(), 0, 0)    // error
On the last line I get this error:

Error XS9052: "In .Net you cannot take the address of a method or a function. For callback functions you need to use a delegate instead."

I have read the topic "DELEGATE Statement" in the X# runtime documentation, I have also searched the forums and found a few topics relating to bBrowser that mention this error, but I still do not understand how exactly I should rewrite the EnumFontFamiliesEx call to make it work.

Kees.
User avatar
Chris
Posts: 4906
Joined: Thu Oct 08, 2015 7:48 am
Location: Greece

Re: X# error XS9052 (In .Net you cannot take the address of a method or a function)

Post by Chris »

Hi Kees,

If you port the app with XPorter, it will make the change automatically. If you do not want to use XPorter, but instead do the conversion manually, you can still just do a dummy port of the app, just copy the modified code (together with the new DELEGATE declaration) and then delete it.

I'm not just replying with the needed change here because I could make a typo, while it's safer to just use XPorter to do it right.
Chris Pyrgas

XSharp Development Team
chris(at)xsharp.eu
User avatar
Kees Bouw
Posts: 119
Joined: Wed Nov 06, 2019 11:35 am
Location: Netherlands

Re: X# error XS9052 (In .Net you cannot take the address of a method or a function)

Post by Kees Bouw »

Hi Chris,

Thank you for your reply. I did use the VOXPorter on the .MEF, and the code you see is what came out of it. Do you think it will be different if I use the VOXPorter on the complete .AEF? My version of the VOXPorter is 2.18.0.4, maybe there is a later version that will make the change with the .MEF?

Kees.
User avatar
Chris
Posts: 4906
Joined: Thu Oct 08, 2015 7:48 am
Location: Greece

Re: X# error XS9052 (In .Net you cannot take the address of a method or a function)

Post by Chris »

Hi Kees,

Ah yes, that must be it. Especially if the function is defined in a different module, so the exporter did not know that you are calling a function just by the .mef. Please do use the aef instead.
Chris Pyrgas

XSharp Development Team
chris(at)xsharp.eu
User avatar
Kees Bouw
Posts: 119
Joined: Wed Nov 06, 2019 11:35 am
Location: Netherlands

Re: X# error XS9052 (In .Net you cannot take the address of a method or a function)

Post by Kees Bouw »

Hi Chris,

Indeed the code is modified when porting the AEF. The functions are in the same MEF however so that could not have been the reason it was not modified. But I will use the AEF's for the VOXPorter in future instead of MEF's even if I need only part of the code.

A note on the side: I think the explanation of the DELEGATE statement in the documentation could be improved. It is now like a summary for someone who already knows how it works. But I can understand that the documentation in general does not have a high priority at the moment :-)

Kees.
User avatar
Chris
Posts: 4906
Joined: Thu Oct 08, 2015 7:48 am
Location: Greece

Re: X# error XS9052 (In .Net you cannot take the address of a method or a function)

Post by Chris »

Hi Kees,

Actually in the last weeks I had worked on some new help topics myself, so I'm hot on this aspect at the moment :) Will put this topic next on the list to update.

In general, a delegate represents a pointer to a method or function, but it is completely strongly typed and must match the parameters of the method(s) it represents. So, if you call such a method through the delegate, the compiler can check if you have passed the correct arguments etc. In contrast, in VO you can also use a method/function pointer to call it (like what happens inside EnumFontFamiliesEx(), which uses the function pointer that you pass it, to call it when it needs to), but you can incorrectly pass it the wrong (type or amount of) arguments, which will lead to incorrect behavior, or a program crash at runtime. In .Net, with a delegate those checks have already been made at compile time.

And that's what VOXporter does, it checks the parameters of the function and defines a DELEGATE type with the same ones. Then it uses that delegate type to create a pointer to the function that your code passes to the WinAPI, and in addition uses the .Net method Marshal.GetFunctionPointerForDelegate(), which in turn converts this .Net style pointer to a WinAPI style pointer that you can pass in your call. For some more info, see https://learn.microsoft.com/en-us/dotne ... ew=net-8.0
Chris Pyrgas

XSharp Development Team
chris(at)xsharp.eu
User avatar
Kees Bouw
Posts: 119
Joined: Wed Nov 06, 2019 11:35 am
Location: Netherlands

Re: X# error XS9052 (In .Net you cannot take the address of a method or a function)

Post by Kees Bouw »

Hi Chris,

Thank you very much for the explanation!

Kees.
Post Reply