Author Topic: PlatformUtils.vb (for dealing with IntersectWith issues)  (Read 1429 times)

0 Members and 1 Guest are viewing this topic.

TheMaster

  • Guest
PlatformUtils.vb (for dealing with IntersectWith issues)
« on: April 12, 2013, 11:11:51 AM »
Posted here because you can't post source code files on Autodesk's brain-dead discussion forum :roll:

Code: (vb.net) [Select]
' PlatformUtils.vb  copyright(c) 2009   Tony Tanzillo
'
'
' Abstract:
'
'   Platform compatibiity helper methods that allow an
'   assembly to run on both 32 and 64 bit systems.
'
'   Refer to PlatformUtils.cs for more complete documentation.
'

Imports System.Runtime.CompilerServices
Imports Autodesk.AutoCAD.DatabaseServices
Imports Autodesk.AutoCAD.Geometry
Imports System.Reflection

<Extension()> _
Public Module PlatformCompatibilityExtensionMethods

   Sub New()
      Dim types1 As Type() = Nothing
      Dim types2 As Type() = Nothing
      If (IntPtr.Size > 4) Then
         types1 = New Type() {GetType(Entity), GetType(Intersect), GetType(Point3dCollection), GetType(Long), GetType(Long)}
         types2 = New Type() {GetType(Entity), GetType(Intersect), GetType(Plane), GetType(Point3dCollection), GetType(Long), GetType(Long)}
      Else
         types1 = New Type() {GetType(Entity), GetType(Intersect), GetType(Point3dCollection), GetType(Integer), GetType(Integer)}
         types2 = New Type() {GetType(Entity), GetType(Intersect), GetType(Plane), GetType(Point3dCollection), GetType(Integer), GetType(Integer)}
      End If
      PlatformCompatibilityExtensionMethods.intersectWithMethod1 = GetType(Entity).GetMethod("IntersectWith", (BindingFlags.Public Or BindingFlags.Instance), Nothing, types1, Nothing)
      PlatformCompatibilityExtensionMethods.intersectWithMethod2 = GetType(Entity).GetMethod("IntersectWith", (BindingFlags.Public Or BindingFlags.Instance), Nothing, types2, Nothing)
   End Sub

   <Extension()> _
   Public Function IntersectWith(ByVal entity As Entity, ByVal other As Entity, ByVal intersectType As Intersect, ByVal points As Point3dCollection) As Integer
      Dim start As Integer = points.Count
      Dim args As Object() = Nothing
      If (IntPtr.Size > 4) Then
         args = New Object() {other, intersectType, points, CLng(0), CLng(0)}
      Else
         args = New Object() {other, intersectType, points, CInt(0), CInt(0)}
      End If
      PlatformCompatibilityExtensionMethods.intersectWithMethod1.Invoke(Nothing, _
         (BindingFlags.NonPublic Or BindingFlags.Static), Nothing, args, Nothing)
      Return (points.Count - start)
   End Function

   <Extension()> _
   Public Function IntersectWith(ByVal entity As Entity, ByVal other As Entity, ByVal intersectType As Intersect, ByVal plane As Plane, ByVal points As Point3dCollection) As Integer
      Dim start As Integer = points.Count
      Dim args As Object() = Nothing
      If (IntPtr.Size > 4) Then
         args = New Object() {other, intersectType, plane, points, CLng(0), CLng(0)}
      Else
         args = New Object() {other, intersectType, plane, points, CInt(0), CInt(0)}
      End If
      PlatformCompatibilityExtensionMethods.intersectWithMethod2.Invoke(Nothing, _
         (BindingFlags.NonPublic Or BindingFlags.Static), Nothing, args, Nothing)
      Return (points.Count - start)
   End Function

   <Extension()> _
   Public Function IntersectWith(ByVal entity As Entity, ByVal other As Entity, ByVal intersectType As Intersect, ByVal points As Point3dCollection, ByVal thisGsMarker As IntPtr, ByVal otherGsMarker As IntPtr) As Integer
      Dim start As Integer = points.Count
      Dim args As Object() = Nothing
      If (IntPtr.Size > 4) Then
         args = New Object() {other, intersectType, points, thisGsMarker.ToInt64, otherGsMarker.ToInt64}
      Else
         args = New Object() {other, intersectType, points, thisGsMarker.ToInt32, otherGsMarker.ToInt32}
      End If
      PlatformCompatibilityExtensionMethods.intersectWithMethod1.Invoke(Nothing, _
         (BindingFlags.NonPublic Or BindingFlags.Static), Nothing, args, Nothing)
      Return (points.Count - start)
   End Function

   <Extension()> _
   Public Function IntersectWith(ByVal entity As Entity, ByVal other As Entity, ByVal intersectType As Intersect, ByVal plane As Plane, ByVal points As Point3dCollection, ByVal thisGsMarker As IntPtr, ByVal otherGsMarker As IntPtr) As Integer
      Dim start As Integer = points.Count
      Dim args As Object() = Nothing
      If (IntPtr.Size > 4) Then
         args = New Object() {other, intersectType, plane, points, thisGsMarker.ToInt64, otherGsMarker.ToInt64}
      Else
         args = New Object() {other, intersectType, plane, points, thisGsMarker.ToInt32, otherGsMarker.ToInt32}
      End If
      PlatformCompatibilityExtensionMethods.intersectWithMethod2.Invoke(Nothing, _
         (BindingFlags.NonPublic Or BindingFlags.Static), Nothing, args, Nothing)
      Return (points.Count - start)
   End Function

   Private intersectWithMethod1 As MethodInfo = Nothing
   Private intersectWithMethod2 As MethodInfo = Nothing

End Module

« Last Edit: April 16, 2013, 01:25:33 PM by TT »

csharpbird

  • Newt
  • Posts: 64
Re: PlatformUtils.vb (for dealing with IntersectWith issues)
« Reply #1 on: April 12, 2013, 11:48:44 PM »
hi,Tony
Can you provide PlatformUtils.cs?

TheMaster

  • Guest
Re: PlatformUtils.vb (for dealing with IntersectWith issues)
« Reply #2 on: April 13, 2013, 08:36:40 AM »
If I recall correctly, this isn't required in versions after AutoCAD 2009,
and doesn't work in later releases, because they fixed the bug, and in
the process, changed the signatures again.

Code: (csharp) [Select]

/// PlatformUtils.cs  copyright(c) 2009  Tony Tanzillo
///
/// AutoCAD .NET Programming Samples: PlatformUtils
///
/// Abstract:
///
///   Platform compatibiity helper methods that allow an
///   assembly to run on both 32 and 64 bit systems.
///
///
/// The Problem:
///
///    There are a number of bugs in AutoCAD's managed runtime
///    that manifest in the form of differing method signatures
///    in the managed runtime libraries included with the 32 and
///    64 bit product releases.
///   
///    One such case involves the Entity's IntersectWith() method,
///    which has different signatures on 32 and 64 bit platforms,
///    requiring different, platform-specific calling code.
///
///    On 32 bit AutoCAD, the last two arguments to IntersectWith()
///    are typed as Int32. On 64 bit AutoCAD, those same arguments
///    are typed as Int64. By default, code compiled with the 32 bit
///    versions of AutoCAD's managed runtime will fail on 64 bit
///    AutoCAD, because the method with the required signature can't
///    be found.
///   
/// The Workaround:
///   
///    The code provided herein serves as a workaround for this bug,
///    that allows a single, platform-neutral managed assembly to
///    run on both 32 and 64 bit AutoCAD without error.
///

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Autodesk.AutoCAD.Geometry;
using System.Reflection;

namespace Autodesk.AutoCAD.DatabaseServices
{

   /// <summary>
   ///
   /// Platform compatibility extension methods for
   /// Autodesk.AutoCAD.DatabaseServices.Entity
   ///
   /// These methods make it easier to deploy a single,
   /// platform-neutral managed assembly that can run
   /// on both 32 and 64 bit AutoCAD.
   ///
   /// </summary>

   public static class PlatformCompatibilityExtensionMethods
   {

      /// <summary>
      /// Extension methods that act as platform-independent
      /// surrogates for the Entity.IntersectWith() method,
      /// allowing a single managed assembly that uses them
      /// to run on both 32 or 64 bit AutoCAD.
      ///
      /// The following extension method overloads are supported:
      ///
      ///   IntersectWith( Entity, Intersect, Point3dCollection );
      ///   IntersectWith( Entity, Intersect, Point3dCollection, IntPtr, IntPtr );
      ///   IntersectWith( Entity, Intersect, Plane, Point3dCollection );
      ///   IntersectWith( Entity, Intersect, Plane, Point3dCollection, IntPtr, IntPtr );
      ///   
      /// The versions which do not require IntPtr as the last two arguments
      /// pass the default of 0 for the GsMarker parameters of the Entity's
      /// IntersectWith() method.
      ///
      /// The versions that require two IntPtr arguments as their last two
      /// parameters convert the passed IntPtr to the required type (Int32
      /// or Int64, depending on the platform the code is running on), and
      /// pass those values for the GsMarker parameters.
      ///
      /// All other parameters are equivalent to the corresponding
      /// parameters of the Entity's IntersectWith() method.
      ///
      /// All overloads return the number of intersections found.
      ///
      /// Use these methods in lieu of Entity.IntersectWith() to
      /// enable your code to run on both 32 and 64 bit systems.
      ///
      /// Performance Issues:
      ///
      /// Because these extension methods use reflection to invoke the
      /// underlying methods they act as surrogates for, they will not
      /// perform as well as direct calls to those underlying methods.
      /// This can be an issue in performance intensive applications,
      /// and in such cases a hand-coded solution that avoids the use
      /// of reflection may be a preferable alternative.
      ///
      /// </summary>


      static PlatformCompatibilityExtensionMethods()
      {
         Object test32 = (Int32) 0;
         Object test64 = (Int64) 0;

         Console.Write( test32 );
         Console.Write( test64 );

         Type[] types1 = null;
         Type[] types2 = null;
         if( IntPtr.Size > 4 )
         {
            types1 = new Type[] { typeof( Entity ), typeof( Intersect ), typeof( Point3dCollection ), typeof( Int64 ), typeof( Int64 ) };
            types2 = new Type[] { typeof( Entity ), typeof( Intersect ), typeof( Plane ), typeof( Point3dCollection ), typeof( Int64 ), typeof( Int64 ) };
         }
         else
         {
            types1 = new Type[] { typeof( Entity ), typeof( Intersect ), typeof( Point3dCollection ), typeof( Int32 ), typeof( Int32 ) };
            types2 = new Type[] { typeof( Entity ), typeof( Intersect ), typeof( Plane ), typeof( Point3dCollection ), typeof( Int32 ), typeof( Int32 ) };
         }

         intersectWithMethod1 = typeof( Entity ).GetMethod( "IntersectWith", BindingFlags.Public | BindingFlags.Instance, null, types1, null );
         intersectWithMethod2 = typeof( Entity ).GetMethod( "IntersectWith", BindingFlags.Public | BindingFlags.Instance, null, types2, null );
      }

      public static int IntersectWith( this Entity entity, Entity other, Intersect intersectType, Point3dCollection points )
      {
         int start = points.Count;
         object[] args = null;
         if( IntPtr.Size > 4 )
            args = new object[] { other, intersectType, points, (Int64) 0, (Int64) 0 };
         else
            args = new object[] { other, intersectType, points, (Int32) 0, (Int32) 0 };
         intersectWithMethod1.Invoke( entity, args );
         return points.Count - start;
      }

      public static int IntersectWith( this Entity entity, Entity other, Intersect intersectType, Point3dCollection points, IntPtr thisGsMarker, IntPtr otherGsMarker )
      {
         int start = points.Count;
         object[] args = null;
         if( IntPtr.Size > 4 )
            args = new object[] { other, intersectType, points, thisGsMarker.ToInt64(), otherGsMarker.ToInt64() };
         else
            args = new object[] { other, intersectType, points, thisGsMarker.ToInt32(), otherGsMarker.ToInt32() };
         intersectWithMethod1.Invoke( entity, args );
         return points.Count - start;
      }

      public static int IntersectWith( this Entity entity, Entity other, Intersect intersectType, Plane plane, Point3dCollection points )
      {
         int start = points.Count;
         object[] args = null;
         if( IntPtr.Size > 4 )
            args = new object[] { other, intersectType, plane, points, (Int64) 0, (Int64) 0 };
         else
            args = new object[] { other, intersectType, plane, points, (Int32) 0, (Int32) 0 };
         intersectWithMethod2.Invoke( entity, args );
         return points.Count - start;
      }

      public static int IntersectWith( this Entity entity, Entity other, Intersect intersectType, Plane plane, Point3dCollection points, IntPtr thisGsMarker, IntPtr otherGsMarker )
      {
         int start = points.Count;
         object[] args = null;
         if( IntPtr.Size > 4 )
            args = new object[] { other, intersectType, plane, points, thisGsMarker.ToInt64(), otherGsMarker.ToInt64() };
         else
            args = new object[] { other, intersectType, plane, points, thisGsMarker.ToInt32(), otherGsMarker.ToInt32() };
         intersectWithMethod2.Invoke( entity, args );
         return points.Count - start;
      }

      static MethodInfo intersectWithMethod1 = null;
      static MethodInfo intersectWithMethod2 = null;


   }
}