Author Topic: P/Invoke trouble  (Read 4282 times)

0 Members and 1 Guest are viewing this topic.

SEANT

  • Bull Frog
  • Posts: 345
P/Invoke trouble
« on: April 19, 2009, 05:16:37 AM »
I’m trying to find the intersection of two lofted surfaces via .NET.  The 2009 BREP namespace only allows direct conversion of solids and regions, as far as I can tell.

There is a method using P/Invoke to expose unmanaged code – as demonstrated in the Autodesk Brep WebCast (http://download.autodesk.com/media/adn/ACADBrep.NETAPIWebcast_24Jun08.zip)

The Brep conversion actually works well enough to allow the construction of a Autodesk.AutoCAD.Geometry.SurfaceSurfaceIntersector object, and even return the geometry to append the appropriate curve. 

The problem is that a minute or two after running the routine AutoCAD crashes.  Testing the routine from the Webcast, it, too, crashes shortly (1 - 3 min) after running.   

It seems like some reference/pointer is left unresolved: Any suggestions on a better dispose method?

The pertinent code from that webcast is shown below -

Code: [Select]
// (C) Copyright 2002-2007 by Autodesk, Inc.
//
// Permission to use, copy, modify, and distribute this software in
// object code form for any purpose and without fee is hereby granted,
// provided that the above copyright notice appears in all copies and
// that both that copyright notice and the limited warranty and
// restricted rights notice below appear in all supporting
// documentation.
//
// AUTODESK PROVIDES THIS PROGRAM "AS IS" AND WITH ALL FAULTS.
// AUTODESK SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTY OF
// MERCHANTABILITY OR FITNESS FOR A PARTICULAR USE.  AUTODESK, INC.
// DOES NOT WARRANT THAT THE OPERATION OF THE PROGRAM WILL BE
// UNINTERRUPTED OR ERROR FREE.
//
// Use, duplication, or disclosure by the U.S. Government is subject to
// restrictions set forth in FAR 52.227-19 (Commercial Computer
// Software - Restricted Rights) and DFAR 252.227-7013(c)(1)(ii)
// (Rights in Technical Data and Computer Software), as applicable.


    public class LibWrap
    {

        // Declaration to P/Invoke the "body" method on the AcDbSurface object
        [DllImport("acdb17.dll",
      EntryPoint = "?body@AcDbSurface@@UBEPAXXZ",
       CallingConvention = CallingConvention.ThisCall)]
        public static extern IntPtr GetSurfBody(IntPtr ths);

        // Declaration to P/Invoke the "setBody" method on the AcDbBody object
        [DllImport("acdb17.dll",
      EntryPoint = "?setBody@AcDbBody@@UAE?AW4ErrorStatus@Acad@@PBX@Z",
       CallingConvention = CallingConvention.ThisCall)]
        public static extern int CreateSurfBdy(IntPtr ths, IntPtr bdyPtr);

    }

        [CommandMethod("SurfaceIntero")]
        static public void SurfaceIntero() // This method can have any name
        {
            // Method to interrogate the AutoCAD Surface object using the B-Rep API
            // Obtain the necessary objects, Database, editor and transaction
            Database db = HostApplicationServices.WorkingDatabase;
            Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;

            Transaction tr = db.TransactionManager.StartTransaction();

            try
            {
                // Prompt to select a surface
                PromptEntityOptions prEntOpt = new PromptEntityOptions("Select a Surface: ");
                prEntOpt.SetRejectMessage("\nPlease select only a Surface");
                prEntOpt.AddAllowedClass(typeof(Autodesk.AutoCAD.DatabaseServices.Surface), true);

                PromptEntityResult prEntRes = ed.GetEntity(prEntOpt);
                Autodesk.AutoCAD.DatabaseServices.Surface surf = (Autodesk.AutoCAD.DatabaseServices.Surface)tr.GetObject(prEntRes.ObjectId, OpenMode.ForRead);

                // Use P/Invoke to obtain the unmanaged body pointer for the surface object. We need to do this
                // because unfortunately, the BRep .NET API does not directly reference the body object within the surface
                IntPtr bdyPtr = LibWrap.GetSurfBody(surf.UnmanagedObject);
                //(Body)Body.Create(bdyPtr, false);

                // Create a new Body object
                Body bdy = new Body();

                // Use P/Invoke to set the newly created body object with the data from the
                // Surface body object
                LibWrap.CreateSurfBdy(bdy.UnmanagedObject, bdyPtr);


                // Now we can create the BRep topology object
                Brep brp = new Brep(bdy);

                //ObjectId[] objIds = { prEntRes.ObjectId };
                //FullSubentityPath fullSubPath = new FullSubentityPath(objIds, SubentityId.Null);
                //BrepEntity brp = new Autodesk.AutoCAD.BoundaryRepresentation.Face(fullSubPath);


                // Find the area of the faces on the Surface
                foreach (Autodesk.AutoCAD.BoundaryRepresentation.Face fc in brp.Faces)
                {
                    ed.WriteMessage("\nThe surface area: {0}", fc.GetSurfaceArea());

                    //fc.Dispose();
                }


                //brp.Dispose();
                tr.Commit();
                bdy.Dispose();

            }
            catch (System.Exception ex)
            {
                ed.WriteMessage("Exception in SurfaceTrav: {0}", ex.Message);

            }
            finally
            {
                tr.Dispose();
            }

        }
Sean Tessier
AutoCAD 2016 Mechanical

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: P/Invoke trouble
« Reply #1 on: April 19, 2009, 09:27:00 AM »
seant, don't have time to have a good look at your code, but ..

Which class do your methods belong to ?

added:
 appears to me that they don't have an owner ..

 with this sort of problem, it may be a good idea to post your full solution folder and a sample drawing, can save a lot of questions later ..
« Last Edit: April 19, 2009, 09:43:29 AM by Kerry Brown »
kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

SEANT

  • Bull Frog
  • Posts: 345
Re: P/Invoke trouble
« Reply #2 on: April 19, 2009, 10:37:54 AM »
The posted code was lifted from the download associated with that webcast.  Attached is my attempt at P/Invoking those same ARX objects to help with a Surface/Surface intersector routine.

It actually works fairly well, as long as I only need to work with Autocad for another 30 seconds or so.  After that. . . . well,  lets just say it crashes so bad you may want to wear safety glasses if you still use a CRT.    :-(
Sean Tessier
AutoCAD 2016 Mechanical

SEANT

  • Bull Frog
  • Posts: 345
Re: P/Invoke trouble
« Reply #3 on: April 19, 2009, 10:44:25 AM »
This would be a sample file saved prior to the aforementioned crash.   
Sean Tessier
AutoCAD 2016 Mechanical

It's Alive!

  • Retired
  • Needs a day job
  • Posts: 8728
  • AKA Daniel
Re: P/Invoke trouble
« Reply #4 on: April 19, 2009, 10:15:24 PM »
You might write Kean and ask, I tried to fiddle around with it for a while but had no luck, Those functions are marked as internal only in the ARX documentation, kind of strange they would publish examples using these mehods.

Personally, I would use C++/CLI to build this app.

SEANT

  • Bull Frog
  • Posts: 345
Re: P/Invoke trouble
« Reply #5 on: April 20, 2009, 03:55:09 AM »
Writing Kean is a good idea.  I’d enjoy a correspondence with him anyway, regardless the possibility he shed some light on this issue.

Daniel, as I recall you discovered another area where the BREP API had caused crashes while processing numerous solids in an oriented bounding box routine.  Did you ever get any feedback on that?

I’m still weighing the Return On Investment with stepping up to C++.  To be honest, I’ve probably spent too much of my free time getting acquainted with .NET. It does seem like a good portion of the total exposed AutoCAD functionality is still ARX only, however. 
Sean Tessier
AutoCAD 2016 Mechanical

It's Alive!

  • Retired
  • Needs a day job
  • Posts: 8728
  • AKA Daniel
Re: P/Invoke trouble
« Reply #6 on: April 20, 2009, 09:08:50 AM »
Daniel, as I recall you discovered another area where the BREP API had caused crashes while processing numerous solids in an oriented bounding box routine.  Did you ever get any feedback on that?

No, I ended up using native code.

I’m still weighing the Return On Investment with stepping up to C++.  To be honest, I’ve probably spent too much of my free time getting acquainted with .NET. It does seem like a good portion of the total exposed AutoCAD functionality is still ARX only, however. 

Yeah, if you need to use classes that aren’t exposed to .NET you can either use C++/CLI to make wrappers of what you need, or just use native code.  I made it a point to learn a little C++/CLI a while back, its actually pretty cool how you can use native code and managed code at the same time. Now I’m have fun learning native C++, 
I don’t need worry about when to call Dispose()

It's Alive!

  • Retired
  • Needs a day job
  • Posts: 8728
  • AKA Daniel
Re: P/Invoke trouble
« Reply #7 on: April 20, 2009, 09:12:57 AM »
BTY, I think the reason your program is crashing is because the p/invoke methods are creating instances of classes and there is no way (no easy way) to do the clean up from C#. so you can only run the program once.
Have a look at this blog
http://blogs.msdn.com/vcblog/archive/2008/12/08/inheriting-from-a-native-c-class-in-c.aspx

SEANT

  • Bull Frog
  • Posts: 345
Re: P/Invoke trouble
« Reply #8 on: April 20, 2009, 05:41:33 PM »
Thanks Daniel.  I’ll try to make sense of that blog.

 I suppose it’s getting close to that time where I give C++ a serious look.  :-o
Sean Tessier
AutoCAD 2016 Mechanical

Kean

  • Newt
  • Posts: 48
Re: P/Invoke trouble
« Reply #9 on: May 08, 2009, 05:27:17 PM »
Hi Sean,

Gopi, the author of the material, looked into this and found the P/Invoked code was keeping a reference to the bdy.

You need to add this line of code where you sould normally call bdy.Dispose():

LibWrap.CreateSurfBdy(bdy.UnmanagedObject, IntPtr.Zero);

Regards,

Kean

Spike Wilbury

  • Guest
Re: P/Invoke trouble
« Reply #10 on: May 08, 2009, 05:48:58 PM »
or maybe what I did here.... might help:

http://www.theswamp.org/index.php?topic=24932.msg301253#msg301253


on how to initialize IntPtr call....

It's Alive!

  • Retired
  • Needs a day job
  • Posts: 8728
  • AKA Daniel
Re: P/Invoke trouble
« Reply #11 on: May 08, 2009, 06:49:32 PM »
Thanks Kean!

SEANT

  • Bull Frog
  • Posts: 345
Re: P/Invoke trouble
« Reply #12 on: May 08, 2009, 08:12:53 PM »
Yes, thanks Kean.

Thanks to you, too, Luis and Daniel.  That link will probably be very informative. . . . with a bit more studying on my part.
Sean Tessier
AutoCAD 2016 Mechanical