Re: .NET Return Conversion to TypedValue
Oh stupid me :Oops: ... I really screwed up the enumerable types. It would convert all nested enumerables to strings of ResultBuffers :banghead:. So ignore my previous codes. Also, notice I've finally figured out what went wrong with the colour coding (Augi keeps on turning my WYSIWYG editor off - thus all pastes are unformatted text), yet another nice thing SharpDevelop does which VS doesn't: Copying code places it on the clipboard together with its formatting and colours!
Here's the fixed version in C#
Code:
public static class ObjectToTypedValue {
#region Public Converter functions
// Blank (like returned by princ)
public static object Convert() {
return new TypedValue((int)LispDataType.None);
}
// Integers (32 bit or other)
public static object Convert(int value) {
return new TypedValue((int)LispDataType.Text, value);
}
// 16 bit integers
public static object Convert(Int16 value) {
return new TypedValue((int)LispDataType.Int16, value);
}
// Doubles
public static object Convert(double value) {
return new TypedValue((int)LispDataType.Double, value);
}
// Strings
public static object Convert(string value) {
return new TypedValue((int)LispDataType.Text, value);
}
// Booleans
public static object Convert(bool value) {
if ((bool) value)
return new TypedValue((int)LispDataType.T_atom);
return new TypedValue((int)LispDataType.Nil);
}
// 2d Points
public static object Convert(Point2d value) {
return new TypedValue((int)LispDataType.Point2d, value);
}
// 3d Points
public static object Convert(Point3d value) {
return new TypedValue((int)LispDataType.Point3d, value);
}
// Catch all other objects including null
public static object Convert(object value) {
if (value == null)
return new TypedValue((int)LispDataType.Nil);
if (value is IEnumerable) {
ResultBuffer rb = new ResultBuffer();
AddToRB(rb, value);
return rb;
}
return Convert(value as string);
}
#endregion
#region Private helper functions for enumerable types
// Unhandled objects in enumerables
private static void AddToRB(ResultBuffer rb, object value) {
rb.Add(Convert(value));
}
// Tuples to dotted pairs
private static void AddToRB(ResultBuffer rb, Tuple<object, object> value) {
rb.Add(new TypedValue((int)LispDataType.DottedPair));
AddToRB(rb, value.Item1);
AddToRB(rb, value.Item2);
rb.Add(new TypedValue((int)LispDataType.ListEnd));
}
// Dictionary entry to association pair
private static void AddToRB(ResultBuffer rb, DictionaryEntry value) {
IEnumerable en = value.Value as IEnumerable;
if (en == null) {
rb.Add(new TypedValue((int)LispDataType.DottedPair));
AddToRB(rb, value.Key);
AddToRB(rb, value.Value);
} else {
rb.Add(new TypedValue((int)LispDataType.ListBegin));
rb.Add(Convert(value.Key));
foreach (object element in en) {
AddToRB(rb, element);
}
}
rb.Add(new TypedValue((int)LispDataType.ListEnd));
}
// Hash tables to association lists
private static void AddToRB(ResultBuffer rb, IDictionary value) {
rb.Add(new TypedValue((int)LispDataType.ListBegin));
IDictionaryEnumerator en = value.GetEnumerator();
while (en.MoveNext()) {
AddToRB(rb, en.Current);
}
rb.Add(new TypedValue((int)LispDataType.ListEnd));
}
// Lists, collections and arrays to Lisp Lists
private static void AddToRB(ResultBuffer rb, IEnumerable value) {
rb.Add(new TypedValue((int)LispDataType.ListBegin));
foreach (object element in value) {
AddToRB(rb, element);
}
rb.Add(new TypedValue((int)LispDataType.ListEnd));
}
#endregion
}
Re: .NET Return Conversion to TypedValue
And the VB.Net version
Code:
Public NotInheritable Class ObjectToTypedValue
Private Sub New()
End Sub
#Region "Public Converter functions"
' Blank (like returned by princ)
Public Shared Function Convert() As Object
Return New TypedValue(CInt(LispDataType.None))
End Function
' Integers (32 bit or other)
Public Shared Function Convert(value As Integer) As Object
Return New TypedValue(CInt(LispDataType.Text), value)
End Function
' 16 bit integers
Public Shared Function Convert(value As Int16) As Object
Return New TypedValue(CInt(LispDataType.Int16), value)
End Function
' Doubles
Public Shared Function Convert(value As Double) As Object
Return New TypedValue(CInt(LispDataType.[Double]), value)
End Function
' Strings
Public Shared Function Convert(value As String) As Object
Return New TypedValue(CInt(LispDataType.Text), value)
End Function
' Booleans
Public Shared Function Convert(value As Boolean) As Object
If CBool(value) Then
Return New TypedValue(CInt(LispDataType.T_atom))
End If
Return New TypedValue(CInt(LispDataType.Nil))
End Function
' 2d Points
Public Shared Function Convert(value As Point2d) As Object
Return New TypedValue(CInt(LispDataType.Point2d), value)
End Function
' 3d Points
Public Shared Function Convert(value As Point3d) As Object
Return New TypedValue(CInt(LispDataType.Point3d), value)
End Function
' Catch all other objects including null
Public Shared Function Convert(value As Object) As Object
If value Is Nothing Then
Return New TypedValue(CInt(LispDataType.Nil))
End If
If TypeOf value Is IEnumerable Then
Dim rb As New ResultBuffer()
AddToRB(rb, value)
Return rb
End If
Return Convert(TryCast(value, String))
End Function
#End Region
#Region "Private helper functions for enumerable types"
' Unhandled objects in enumerables
Private Shared Sub AddToRB(rb As ResultBuffer, value As Object)
rb.Add(Convert(value))
End Sub
' Tuples to dotted pairs
Private Shared Sub AddToRB(rb As ResultBuffer, value As Tuple(Of Object, Object))
rb.Add(New TypedValue(CInt(LispDataType.DottedPair)))
AddToRB(rb, value.Item1)
AddToRB(rb, value.Item2)
rb.Add(New TypedValue(CInt(LispDataType.ListEnd)))
End Sub
' Dictionary entry to association pair
Private Shared Sub AddToRB(rb As ResultBuffer, value As DictionaryEntry)
Dim en As IEnumerable = TryCast(value.Value, IEnumerable)
If en Is Nothing Then
rb.Add(New TypedValue(CInt(LispDataType.DottedPair)))
AddToRB(rb, value.Key)
AddToRB(rb, value.Value)
Else
rb.Add(New TypedValue(CInt(LispDataType.ListBegin)))
rb.Add(Convert(value.Key))
For Each element As Object In en
AddToRB(rb, element)
Next
End If
rb.Add(New TypedValue(CInt(LispDataType.ListEnd)))
End Sub
' Hash tables to association lists
Private Shared Sub AddToRB(rb As ResultBuffer, value As IDictionary)
rb.Add(New TypedValue(CInt(LispDataType.ListBegin)))
Dim en As IDictionaryEnumerator = value.GetEnumerator()
While en.MoveNext()
AddToRB(rb, en.Current)
End While
rb.Add(New TypedValue(CInt(LispDataType.ListEnd)))
End Sub
' Lists, collections and arrays to Lisp Lists
Private Shared Sub AddToRB(rb As ResultBuffer, value As IEnumerable)
rb.Add(New TypedValue(CInt(LispDataType.ListBegin)))
For Each element As Object In value
AddToRB(rb, element)
Next
rb.Add(New TypedValue(CInt(LispDataType.ListEnd)))
End Sub
#End Region
End Class
Re: .NET Return Conversion to TypedValue
hi everyone,
this code does exctly what i need,
but there is no usage sample, and by the way i do, i've a System.StackOverflowException error
This code is complicated for my level with surcharge and something like recursivity,
and when i make a step to step debugging, it seems to turn into an infinite loop.
My sample is just designed to show interactions between lisp and .net, so it's really silly.
so here my code :
Code:
'for sample, definy myvar like following :
'(setq myvar "myValue")
'then answer 'myvar' at the prompt
<CommandMethod("EvalLispSymbol")> _
Public Sub EvalLispSymbol()
Dim doc As Document = Application.DocumentManager.MdiActiveDocument
Dim ed As Editor = doc.Editor
Dim strEval As String = ed.GetString("Name of the lisp symbol ?").StringResult
ed.WriteMessage(vbLf & "NetGetLispSym " & strEval & " :")
' get the 'lst2' variable value
'Dim output As ResultBuffer = AcadExtensions.LispExtensions.NetGetLispSym(strEval)
Dim output As Object = doc.GetLispSymbol(strEval)
Dim Rboutput As ResultBuffer = ObjectToTypedValue.Convert(output)
' print the value to the commande line
ed.WriteMessage(vbLf & "Value of the lisp symbol '" & strEval & " as resultBuffer :")
For Each tv As TypedValue In Rboutput
ed.WriteMessage(vbLf & "Type: {0}" & vbTab & "Value: {1}", tv.TypeCode, tv.Value)
Next
ed.WriteMessage(vbLf & "Now make a !lst to verify that lst = " & strEval & " :")
doc.SetLispSymbol("lst", output)
End Sub
gégé
Re: .NET Return Conversion to TypedValue
It seems the issue is that a string type is considered an IEnumerable. Thus that code generates an infinite recursive loop - i.e. a stack frame overflow error. Very strange that I didn't pick it up before, I've not heard that it was changed recently. The fix would be to check for string types before checking for enumerable types. Something like this:
C#
Code:
// Catch all other objects including null
public static object Convert(object value)
{
if (value == null)
return new TypedValue((int)LispDataType.Nil);
if (value is string)
{
return Convert(value as string);
}
if (value is IEnumerable)
{
ResultBuffer rb = new ResultBuffer();
AddToRB(rb, value);
return rb;
}
return value;
}
And converted to VB.NET using SnippetConverter
Code:
' Catch all other objects including null
Public Shared Function Convert(value As Object) As Object
If value Is Nothing Then
Return New TypedValue(CInt(LispDataType.Nil))
End If
If TypeOf value Is String Then
Return Convert(TryCast(value, String))
End If
If TypeOf value Is IEnumerable Then
Dim rb As New ResultBuffer()
AddToRB(rb, value)
Return rb
End If
Return value
End Function
Re: .NET Return Conversion to TypedValue
Hi,
thanks for the quick reply,
now there is no more loop, but i've always a problem to correctly use your conversion:
i've an error because the conversion return an object else to a result-buffer:
What is wrong with that :
Code:
Dim Rboutput As ResultBuffer = ObjectToTypedValue.Convert(output)
Thanks,
Gégé
Re: .NET Return Conversion to TypedValue
It always returns a TypedValue. If the object input into it is a collection of objects (i.e. an IEnumerable), that TypedValue wraps around a result buffer of TypedValues (one each for each item in the collection).
If it always returns a ResultBuffer, then it will work wrong: If that was the case and you sent it (say) a number, the result buffer would thus turn it into a list with a number inside it. I.e. it would be like you did the following:
Code:
(setq var 100)
!var
(100) ;Instead of just 100
Re: .NET Return Conversion to TypedValue
hello,
so i've changed my usage of your class,
no i check what it returns :
this wor fine with
(setq myvar "mystringvalue")
Code:
Dim strEval As String = "myvar"
Dim output As Object = doc.GetLispSymbol(strEval)
Dim ResOTTV As Object = ObjectToTypedValue.Convert(output)
Dim Rboutput As New ResultBuffer
If TypeOf ResOTTV Is TypedValue Then
Rboutput.Add(ResOTTV)
ElseIf TypeOf ResOTTV Is ResultBuffer Then
Rboutput = ResOTTV
Else
Rboutput = Nothing
End If
But with (setq myvar '(1 1) )
output type is point2d
but the class ObjectToTypedValue does'nt intercept it as point2d:
only
Code:
' Catch all other objects including null
Public Shared Function Convert(value As Object) As Object
is evaluated, so it returns nothing
My deserve is to prepare a template Vb project inclunding everythings needed to work with LIsp>NET>lisp
so your class is realy usefull
Gégé
Re: .NET Return Conversion to TypedValue
A few items to note here:
- The intent of this is to convert a DotNet type into a TypedValue ready for sending back to Lisp, not to take what lisp gives you and convert it back to what lisp expects. I.e. reading from the lisp symbol, you get it converted to DotNet types only if it converts to a basic DotNet type. If the symbol contains something like a list, then the GetLispSymbol actually gives you a TypedValue - i.e. again, you're trying to convert a typedvalue into a typedvalue - makes no sense.
- The library is intended to work on operator overloads. This won't work if you simply box all the values into an object. If you want that, then look at Peter's original code - though as I stated in the 2nd post, it would be more efficient to select on TypeCode instead of Type.
- My code is definitely just intended to show what can be done.
- Please be patient as I'm not very into DotNet for ACad anymore, rather more focused on Revit and C# than ACad and VB. So may make a few mistakes, miss some point in the VB codes, or forget something I only did a few years ago.
However, looking through that I must say I'd definitely go with some form of combination between my codes and Peter's. The reason being that mine would only work well if your values are statically typed and not boxed. Peter's would work in all cases, just being a bit slower as it uses reflection to obtain the type of the boxed object.
Re: .NET Return Conversion to TypedValue
Hi,
i think i've made a big mismatch with (setq myvar '(1 1) ) !
now i know it must work,
so i 've to find a better sample for your class ...
regards,
Gégé