WB and CLR Assemblies

Started by stanl, November 16, 2013, 04:09:07 AM

Previous topic - Next topic

stanl

Take this as chapter 2 of the CLR/VB.NET thread......

In our last chapter we determined that VB.NET function(s)/sub(s) could be turned into a managed assembly (i.e. a DLL created directly from WB) and called from a WB script (with a version of WB that supports CLR).  That being said....

1. The initial 'code' used to produce the CopyToClipboard() method alluded to a Namespace. So any VB code you wish to use with WB via the CLR should have a namespace?

2. Is the process similar if using C# code?

3. As for limitations:  I could, for example, create a managed assembly from VB code that performs conversions... i.e. Pounds to Euros, and call the PoundsToEuros(pound) function through the CLR. However, although I could create a DLL from VB code that produced a grid and possibly display the grid in VB, the majority of the functionality of the grid would not be available.

Although I understand answers to questions like this can involve technicalities and often the person asking feels somewhat dumb - I have always felt WB was for practicioners not developers and therefore real-world cando/cannotdo scenarios provide a better way to sort the technicalities.   

td

Quote from: stanl on November 16, 2013, 04:09:07 AM
Take this as chapter 2 of the CLR/VB.NET thread......

In our last chapter we determined that VB.NET function(s)/sub(s) could be turned into a managed assembly (i.e. a DLL created directly from WB) and called from a WB script (with a version of WB that supports CLR).  That being said....

1. The initial 'code' used to produce the CopyToClipboard() method alluded to a Namespace. So any VB code you wish to use with WB via the CLR should have a namespace?

This is covered in the documentations for the ObjectClrNew function:  "(s) typename: The name of a Framework based class, structure or enumeration. The name must be fully qualified by including the dot (.) separated namespace prefixed to the type's immediate name.  The namespace name and immediate name must also be separated by a dot character."

Quote
2. Is the process similar if using C# code?

See above.

Quote
3. As for limitations:  I could, for example, create a managed assembly from VB code that performs conversions... i.e. Pounds to Euros, and call the PoundsToEuros(pound) function through the CLR. However, although I could create a DLL from VB code that produced a grid and possibly display the grid in VB, the majority of the functionality of the grid would not be available.
Also partially covered in the dotNet topic in the help file: "Delegates and event callbacks are not supported. (This limits the effectiveness of UI related classes.)".  In most cases you can get a UI to display but you can't respond to user input because that requires the use of a special type of delegate called an event handler. 

"No one who sees a peregrine falcon fly can ever forget the beauty and thrill of that flight."
  - Dr. Tom Cade

stanl

Quote

This is covered in the documentations for the ObjectClrNew function:  an event handler.
All well and good, but the point I was trying to make was about practical steps. For example, assume someone tries the steps to create and execute the ClipBoardCopy() method from the previous thread. Then they try similar code

Imports Microsoft.VisualBasic
Imports System
Namespace Conversion
  Public Class Euro
    Public Shared Sub Cvt(ByVal xValue as Decimal)
     Dim result as Decimal
       result = (xValue * 1.34509)
    End Sub
  End Class
End Namespace

which they run through Deana's script and produce EURO.dll (attached).
Then they try to execute the method using your appbase script.
Code (WINBATCH) Select

ObjectClrOption( "appbase", dirscript() )
ObjectClrOption("use", "Euro")
oTest = ObjectClrNew("Conversion.Euro")
v = oTest.Cvt(16.0)
oTest=0
Message("",v)
Exit



But get [error attached as jpeg]. Point being, there needs to be some simple how-to guidelines rather than just another RFM. 

td

Quote from: stanl on November 17, 2013, 07:30:05 AM
But get [error attached as jpeg]. Point being, there needs to be some simple how-to guidelines rather than just another RFM.

We certainly do not intended to start providing support for  VB .Net or C# programming.  MSFT has already done that.  Their documentation for managed code languages and the FCL is quite good and we already have more than enough to do helping WinBatch users learn and use the many features of the WIL language.  We certainly do encourage users to experiment with creating dotNet assemblies but that comes with the expectation that they also have at least some fluency in the managed code language they are using.

I suspect the reason  for your error is covered in the 'manual' and very little to do with the fact that you are building an assembly on the fly.  From the manual: "Both member overloading and the fact that WinBatch cannot query the object for type information before making a member call as it does with regular COM Automation references mean that the colon (:) type qualifier needs to be used more frequently on CLR object member parameters. Fortunately, WinBatch will take standard variant type names like BSTR, UI8, BOOLEAN, R8, e.g., and convert them to equivalent Framework types automatically. It will also automatically deduce the correct Framework type for variant variables passed as parameters to a member without needing to specify a type with the colon qualifier."

In your specific case, try adding decimal: or System.Decimal: to your method parameter so WinBatch can generate a method signature that matches that of your method's.  By default WinBath converts floating point numbers to 'System.Double' and your method's signature specifies 'System.Decimal'.   You would have the same problem if you were using an FCL class that required decimal input unless it had an overload that accepted doubles, of course. 

Again your error has nothing to do we the fact that you created your own assembly other than you choice of method parameters and there is absolutely nothing wrong with that choice.

"No one who sees a peregrine falcon fly can ever forget the beauty and thrill of that flight."
  - Dr. Tom Cade

td

FWIW, I do think a  type conversion table mapping WIL to COM to FCL types might make a good addition to the Tech. DB.

And if by tutorial, you mean a general CLR usage tutorial and then I can see where that might be useful.  In lieu of  that most COM usage and techniques can be applied to CLR based classes. The one important addition is that if you get a method not found error and you know the method exists, check the type(s) of your parameter(s).
"No one who sees a peregrine falcon fly can ever forget the beauty and thrill of that flight."
  - Dr. Tom Cade

stanl

I appreciate your comments. You are correct about the type conversion. Calling a pounds to Euro conversion will work if the type is declared in the code (this time using a Function, rather than a sub)\

Imports Microsoft.VisualBasic
Imports System
Namespace Conversion
  Public Class Euro
    Public Function Cvt(xValue)
     Dim result as Decimal 
   result = Decimal.Parse(xValue)
       Return(result * 1.34509)
    End Function
  End Class
End Namespace


If used to create the Euro.dll (again attached) will work.  I am in no way suggesting you write a complete 'how-to' - I am posting things like this to generate a larger audience contributing to the CLR. I cannot explain why the sub code fails and the function succeeds although both create a dll. But, it appears to be excellent example for those stepping into the CLR, so that threads like this are not repeated ad infinitum.
This goes back to your comments about the CLR being  functional alternative to creating Extenders.

td

Strange as it may seem, you can't return a value from a 'sub' in VB .Net.  That is why 'function' works but 'sub' does not.

 
"No one who sees a peregrine falcon fly can ever forget the beauty and thrill of that flight."
  - Dr. Tom Cade

stanl

Quote from: td on November 17, 2013, 02:47:35 PM
Strange as it may seem, you can't return a value from a 'sub' in VB .Net.  That is why 'function' works but 'sub' does not.



But if you write the function as Public Function Cvt(xValue AS Decimal) AS Decimal it will also fail. Referring to your earlier statement

Quote
In your specific case, try adding decimal: or System.Decimal: to your method parameter so WinBatch can generate a method signature that matches that of your method's.

are you saying replace
v = oTest.Cvt(16.0)

with
v = oTest.Cvt(Decimal:16.0)

or define xvalue as a .NET Decimal

then
v = oTest.Cvt(xvalue)








td

You are confusing to different issues.  One involves the fact that you can't return a value from sub in VB .Net.  This is strictly a VB .Net limitation and has nothing what so ever to do with WinBatch. 

The other is that you need to specify the type of the parameter to your method because that type is Decimal.   WinBatch does not automatically convert doubles to the CLR type System.Decimal.  It quite logical converts doubles to System.Double. Because parameter type is used by the CLR type resolver to identify class members and there isn't a method with the name 'Cvt' that takes a parameter of type Double, you need to tell it the type of the parameter.  You do this by prepending the DECIMAL: type specifier to the parameter. Adding the type specifier causes WinBatch to convert the parameters value to variant type Decimal and instruct the CLR to look for a method named 'Cvt' that takes a parameter of type 'System.Double'.

If you create a function with this VB .Net code:
Code (winbatch) Select

code = 'Imports Microsoft.VisualBasic':@lf
code = code: 'Imports System':@lf
code = code: 'Namespace Conversion':@lf
code = code: '  Public Class Euro':@lf
code = code: '    Public Function Cvt(xValue AS Decimal) As Decimal':@lf
code = code: '      Dim result as Decimal':@lf
code = code: '      result = (xValue * 1.34509)':@lf
code = code: '      return result':@lf
code = code: '    End function':@lf
code = code: '  End Class':@lf
code = code: 'End Namespace'


Call it like this:
Code (winbatch) Select

v = oTest.Cvt(decimal:16.0)

"No one who sees a peregrine falcon fly can ever forget the beauty and thrill of that flight."
  - Dr. Tom Cade