User Tools

Site Tools


vo_to_net:pcall

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
vo_to_net:pcall [2018/07/08 16:24] wolfgangriedmannvo_to_net:pcall [2018/07/29 05:22] (current) wolfgangriedmann
Line 1: Line 1:
 ====== PCall vs PCallNative ====== ====== PCall vs PCallNative ======
  
-In the first Vulcan versions, ''PCall'' was not supported anymore, so this code would not have worked+''PCall()'' and ''PCallNative()'' are pseudo-functions or intrinsic functions - they do not need any runtime because they are replaced by the compiler. 
-<code>PCallptrFunction, @strWinOsVersionInfo )</code> + 
-There was only a function ''PCallNative'' to use (knowing the return type): +The X# compiler needs a typed function pointer for ''PCall()'' to work (and you need the compiler switch /vo6 "Resolve function pointers to PTR")
-<code>PCallNative<int>ptrFunction, @strWinOsVersionInfo )</code> +<code visualfoxpro>STATIC FUNCTION __GetRealOsVersion( struOS AS _winOSVERSIONINFOEX) AS DWORD PASCAL  // typed function pointer 
-Using the Vulcan runtimeit was preferred to use ''PCallNative'', but in the X# runtime the development team used another approach, so they recommend to use again ''PCall''.+  RETURN 0 
 +.... 
 +local hFunc as __GetRealOsVersion ptr 
 +dword( _cast , PCALLhFunc ,@struOS) )</code> 
 +The alternative (to not define such a function) is to use ''PCallNative()''
 +<code visualfoxpro>local hFunc as ptr 
 +PCALLNative<dword>hFunc ,@struOS )</code> 
 + 
 +The .NET way would be the definition of a delegate (i.e. a typed function pointer). Please see [[:delegates|Delegates]].  
 +A sample for the delegate version is the following
 +<code visualfoxpro>delegate RtlGetVersionDelegatestruOS as _winOSVERSIONINFOEX) as dword 
 +local oFunc as RtlGetVersionDelegate 
 + 
 +oFunc := ( RtlGetVersionDelegate ) Marshal.GetDelegateForFunctionPointer( hFuncTypeOf( RtlGetVersionDelegate ) ) 
 +oFunc:Invoke( @struOS )</code> 
 + 
 +To simplify the codea static method could help: 
 +<code visualfoxpro>static class DelegateHelper 
 + 
 +static method CreateDelegate<T>( hFunc as ptr ) as T 
 +  local oFunc as T 
 +  local oDelegate as object 
 + 
 +  oDelegate := Marshal.GetDelegateForFunctionPointer( hFunc, TypeOf( T ) ) 
 + 
 +  oFunc := ( T ) oDelegate 
 + 
 +  return oFunc 
 + 
 +end class</code> 
 +and to be used: 
 +<code visualfoxpro>oFunc := DelegateHelper.CreateDelegate<RtlGetVersionDelegate>( hFunc )</code> 
 +(Code courtesy of Chris Pyrgas) 
 + 
 +The X# development team recommends the use of ''PCall()'' over ''PCallNative()'' because the X# compiler will build a delegate from the typed function pointer and use it.
  
 The following was stated by a member of the development team: The following was stated by a member of the development team:
 +
 ''A delegate is created by the compiler and the parameters for the delegate have to be determined by the compiler . In the case of PCallNative it looks at the actual arguments to "guess" the types. The return type is then the type as specified in the code. In the case of PCall it copies both the parameter types and return value of the function in the declaration to the delegate. The compiler then emits the code to use the native function pointer and call this with the managed delegate. ''A delegate is created by the compiler and the parameters for the delegate have to be determined by the compiler . In the case of PCallNative it looks at the actual arguments to "guess" the types. The return type is then the type as specified in the code. In the case of PCall it copies both the parameter types and return value of the function in the declaration to the delegate. The compiler then emits the code to use the native function pointer and call this with the managed delegate.
 For this reason I would recommend using PCall because the function name used in the declaration gives you full control of the parameter types in the delegate.'' For this reason I would recommend using PCall because the function name used in the declaration gives you full control of the parameter types in the delegate.''
  
-Please see major details in the X# Forum discussion:+Please see more details in the X# Forum discussion:
 [[https://www.xsharp.info/forum/public-product/752-voxporter-icon-naming-problem#5355|www.xsharp.info/forum/public-product/752-voxporter-icon-naming-problem]] [[https://www.xsharp.info/forum/public-product/752-voxporter-icon-naming-problem#5355|www.xsharp.info/forum/public-product/752-voxporter-icon-naming-problem]]
 +
 +Please note:
 +
 +''PCallNative()'' does not need anything special - it needs only that the return type is specified, so it is the simplest call (and of course the one with the most risk to do something wrong).
 +
 +''PCall()'' needs a correct declaration of the prototype of the called function, and generates code from it. But since also PCall() assumes something, it has some risk.
 +
 +The best option to call a function from a dynamically loaded DLL is to define a delegate, assign the function pointer to it and call then the delegate.
 +
 +In VO, dynamically loading DLLs and executing function from it was interesting to make the application loading times shorter, but in .NET thanks to its lazy loading this is not more necessary.
 +
 +Executing functions dynamically is only needed when you are not sure that the functionality is installed, or if you are using different versions dependent on some other parameters like OS version or 3rd party DLL version.
vo_to_net/pcall.1531067043.txt.gz · Last modified: 2018/07/08 16:24 by wolfgangriedmann