Page 1 of 1
X# error XS9052 (In .Net you cannot take the address of a method or a function)
Posted: Tue Jan 09, 2024 7:07 pm
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.
Re: X# error XS9052 (In .Net you cannot take the address of a method or a function)
Posted: Tue Jan 09, 2024 7:20 pm
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.
Re: X# error XS9052 (In .Net you cannot take the address of a method or a function)
Posted: Wed Jan 10, 2024 8:15 am
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.
Re: X# error XS9052 (In .Net you cannot take the address of a method or a function)
Posted: Wed Jan 10, 2024 8:32 am
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.
Re: X# error XS9052 (In .Net you cannot take the address of a method or a function)
Posted: Wed Jan 10, 2024 9:01 am
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.
Re: X# error XS9052 (In .Net you cannot take the address of a method or a function)
Posted: Wed Jan 10, 2024 6:07 pm
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
Re: X# error XS9052 (In .Net you cannot take the address of a method or a function)
Posted: Fri Jan 12, 2024 8:33 am
by Kees Bouw
Hi Chris,
Thank you very much for the explanation!
Kees.