] extern bool Clos...">

Is there any compatible with C # and VB System.Void * in F #? (To close a pointer to an unmanaged Alloc?)

[<DllImport("kernel32")>] extern bool CloseHandle(System.Void* handle); //System.Void also throws same error //extern bool CloseHandle(System.Void handle); 

gives an error:

'System.Void' can only be used as 'typeof' in F #

but

  extern bool CloseHandle(typeof<System.Void> handle); 

not compiled. Same mistake

"System.Void can only be used as typeof ..."

F # void* compiles

  extern bool CloseHandle(void* handle); 

but using it in C # causes a development-time conversion error

 public void CloseBeforeGarbageCollection(IntPtr someAllocIntPtr) { //test unmanaged block var result = CloseHandle(someAllocIntPtr.ToPointer()); return result; } 

'cannot convert from' void * 'to' System.IntPtr '

although a managed intptr transfer will compile

 //test managed IntPtr var result = CloseHandle(someAllocIntPtr); //throws error at runtime 

but when someAllocIntPtr is the result of Marshal.AllocHGlobal , it throws an exception at runtime External component has thrown an exception. . As I understand it, this is because someAllocIntPtr (as a result of Marshal.AllocHGlobal) is a technically managed pointer to an unmanaged pointer, not a normal IntPtr. Peter Ritchie noticed this in response to his answer here: System.Runtime.InteropServices.SEHException (0x80004005): An external component threw an exception

The only way to avoid this Exception Exception is to wrap the handle in a subclass of SecureHandle() , but I think it's against the ref-ref\out-out rule in MSDN: CA1021: Avoid parameters . IE, System.Void* realPointer = someAllocIntPtr.ToPointer() is an ACTUAL pointer (a reference to an unmanaged pointer), or, in other words, SecureHandle safeHandle = new SecureHandle(someAllocIntPtr) is actually a " other link - actual pointer" link and not must be transmitted with the keywords out or ref in accordance with the MSDN article.

+5
source share
1 answer

I did a little test as follows:

In the f # assembly (dll library), I have the following module:

 module MyWin32 open System open System.Runtime.InteropServices [<DllImport("kernel32")>] extern bool CloseHandle(IntPtr handle); [<DllImport("kernel32")>] extern IntPtr CreateToolhelp32Snapshot(IntPtr flag, IntPtr procId); 

In the F # console program, which has a link to the aforementioned lib, I:

 open System open System.Runtime.InteropServices open MyWin32 [<EntryPoint>] let main argv = let handle = CreateToolhelp32Snapshot(IntPtr(4), IntPtr(System.Diagnostics.Process.GetCurrentProcess().Id)) printfn "%A" handle printfn "%b" (CloseHandle handle) // A HGlobal should always be released by FreeHGlobal let intPtr = Marshal.AllocHGlobal(1024) Marshal.FreeHGlobal(intPtr) 

And in the C # console program that references the lib above, I:

 using System; namespace CSTest { class Program { static void Main(string[] args) { var handle = MyWin32.CreateToolhelp32Snapshot(new IntPtr(4), new IntPtr(System.Diagnostics.Process.GetCurrentProcess().Id)); Console.WriteLine(handle); Console.WriteLine(MyWin32.CloseHandle(handle)); Console.ReadLine(); } } } 

Both tests F # and C # are compiled and executed as completed. Hope this helps you.

About void *:

The F # MyWin32 assembly change shown above using IntPtr to void * substitution still works for F # and C # clients without any other modifications (the C # metadata code for MyWin32 replaces void * with IntPtr):

 module MyWin32 open System open System.Runtime.InteropServices [<DllImport("kernel32")>] extern bool CloseHandle(void* handle); [<DllImport("kernel32")>] extern void* CreateToolhelp32Snapshot(IntPtr flag, IntPtr procId); 

So, the conclusion of the above small tests is that you can use void * in F # as a valid substitution for IntPtr.

I think that you need to use IntPtr.ToPointer () in the insecure section {} in C #, since pointers only make sense in insecure mode in C #.

+1
source

Source: https://habr.com/ru/post/1257486/


All Articles