Author Topic: Calling .net LispFunction while processing DBX  (Read 9135 times)

0 Members and 1 Guest are viewing this topic.

CADDOG

  • Newt
  • Posts: 82
  • wishbonesr
Calling .net LispFunction while processing DBX
« on: October 25, 2012, 01:21:39 PM »
I'm calling a .net LispFunction while processing through DBX.
The LispFunction originally uses the Application.DocumentManager.MdiActiveDocument to search for the supplied ename/ObjectId, then I tweaked it to cycle the Application.DocumentManager looking for the ObjectId.  If the drawing isn't open, then it will not find the ObjectId/ename. The function using MdiActiveDocument, of course, is not going to find the supplied ename from another doc.

So is there a way to get the appropriate Database to GetObject() the ObjectId I supply when it came from a document opened in lisp via DBX?
That's a mouthfull

Is there a way to use my Lispfunction in this manner via DBX object?

Edit Notes: I reread this.  It's not easy to explain. sorry. 
Using LeeMac ODBX wrapper http://www.lee-mac.com/odbxbase.html
« Last Edit: October 25, 2012, 02:05:55 PM by CADDOG »

T.Willey

  • Needs a day job
  • Posts: 5251
Re: Calling .net LispFunction while processing DBX
« Reply #1 on: October 25, 2012, 03:41:29 PM »
I'm not sure I understand what you trying to do, but I would pass the handle of the entity that you want, as that doesn't change per opening.  As far as I understand it, object ids are assigned per opening, so they can change, but the handle will not change.
Tim

I don't want to ' end-up ', I want to ' become '. - Me

Please think about donating if this post helped you.

BlackBox

  • King Gator
  • Posts: 3770
Re: Calling .net LispFunction while processing DBX
« Reply #2 on: October 25, 2012, 03:49:33 PM »
Tim, if I am understanding the OP correctly, he's trying to refactor his code to access the ObjectDBX Document Object in lieu of the Application.DocumentManager.MdiActiveDocument Object.

Never tried this before myself, but perhaps this quick search result may be of help:

Quote from: AutoCAD .NET Developer's Guide

Use COM Interoperability with .NET

Microsoft Visual Studio can utilize both native .NET and COM interfaces in the same project. By utilizing COM interop, you can migrate existing code that might have been written in Visual Basic 6 or VBA without having to completely rewrite it. To access AutoCAD automation objects from a project created in Microsoft Visual Studio, create references to the following files:

    The AutoCAD 2010 type library, acax18enu.tlb, located at <drive>:\Program Files\Common Files\Autodesk Shared.

    The AutoCAD/ObjectDBX Common 18.0 type library, axdb18enu.tlb, located at <drive>:\Program Files\Common Files\Autodesk Shared.

<snip>
"How we think determines what we do, and what we do determines what we get."

CADDOG

  • Newt
  • Posts: 82
  • wishbonesr
Re: Calling .net LispFunction while processing DBX
« Reply #3 on: October 25, 2012, 04:33:56 PM »
RenderMan is correct.
I'm so new at .NET it's not even funny (3 weeks).  Let alone the API of Autocad.
So your suggestion, which I remember reading sounds like the missing link.

I'm going to try two different ways, because I want to stay away from COM if possible.  The reason?  My current LispFunction is so simple, and doesn't need to be in .net.  This go-around is a proof of concept as I migrate more 'complex lisp' or 'impossible to do in lisp' functions to .net.  Bulk processing is a major part of years of lisp code that has been tweaked to work with dbx (getvar, selectionsets, etc).  If I fail, then it's a realization that I need to develop the more complicated bulk processing in .net.  That's a hard bullet to bite right now, due to the learning curve.

First I'm going to shoot at opening the dwg by suppying the path\file and use ReadDwgFile() - which means I'm openign the file twice (ha).  Once in dbx and the other .net

Second I'm going to attempt COM if the first attempt falls flat (at this point it's like looking into a cave without a flashlight).  If I do supply the vla-item to lisp, do you know what LispDataType it will be assigned to?
Currently, I get the following error:
Code: [Select]
invalid data type or data overflow: #<VLA-OBJECT IAcadDocument 0000000028dcfc60>The LispFunction itself is made to never fail (ha), and return either t or nil in all situations.  I think that # is supposed to be telling me something (clue).

Thanks for the feed back fellas.
« Last Edit: October 25, 2012, 04:39:02 PM by CADDOG »

BlackBox

  • King Gator
  • Posts: 3770
Re: Calling .net LispFunction while processing DBX
« Reply #4 on: October 25, 2012, 04:40:47 PM »
Not sure that's the best approach (not that I can offer better at the moment), attempting to open the file twice, once in ObjectDBX, and once in .NET (isn't that still opening within DocumentManager, unless using RealDWG? :?).

As for what LispDataType enums are available, just search for AutoDesk.AutoCAD.Runtime.LispDataType in Object Browser:wink:
"How we think determines what we do, and what we do determines what we get."

CADDOG

  • Newt
  • Posts: 82
  • wishbonesr
Re: Calling .net LispFunction while processing DBX
« Reply #5 on: October 25, 2012, 05:02:07 PM »
...
...(isn't that still opening within DocumentManager, unless using RealDWG? :?).

I don't know.  :ugly: Breaking till it works is my preferred method to figure something out.
I am not a Card Carrying member of RealDWG.
See I thought dbx is using the documentmanger, but as I said before (strike-through), I cycled through the documents in documentmanager with no results.  This almost makes me believe that dbx is operating in a seperate application instance???
There's just so many things I'm ignorant on, I can't draw conclusions.  Doesn't help if it hasn't been attempted before.
Edit:
You know what...I think that tells me what I should be doing.


As for what LispDataType enums are available, just search for AutoDesk.AutoCAD.Runtime.LispDataType in Object Browser:wink:

Did that.  Didn't see anything that could equal the container for a vla-object, even if I did use COM in my project, I don't think I can pass a vla-object from lisp to a COM enabled .net project.
Thinking I am going to have to overload the ResultBuffer...
Just kidding.

BlackBox

  • King Gator
  • Posts: 3770
Re: Calling .net LispFunction while processing DBX
« Reply #6 on: October 25, 2012, 05:34:47 PM »
I too am very new to .NET development, so take what I have said with a grain of salt.

I know that both ObjectDBX, and RealDWG function outside of the AutoCAD application, but I am unsure of their being on the same, or different thread (above my knowledge base). Also, I have never used RealDWG before.

Hopefully someone much more knowledgeable will be along shortly.
"How we think determines what we do, and what we do determines what we get."

CADDOG

  • Newt
  • Posts: 82
  • wishbonesr
Re: Calling .net LispFunction while processing DBX
« Reply #7 on: October 25, 2012, 07:57:02 PM »
Grain of salt...
Naw, bouncing ideas off of anybody sometimes produces results, by thinking beyond the box you hold yourself to.  Sometimes I'll vent to my wife about some project frustrations, and the patient and adoring wife she is, she just nods cuz she knows she just needs to be attentive and give me an ear...  And then BAM!  An idea strikes me, and I'm an hour away from my coding computer at work. HA.

But I think I'm going to drop it.  I don't see anyone attempting to work with dbx in lisp and use functions in .net.  It just so happens, this project requires me to mass edit files, and I needed something quicker and more reliable than my current xref status tester in lisp.

T.Willey

  • Needs a day job
  • Posts: 5251
Re: Calling .net LispFunction while processing DBX
« Reply #8 on: October 25, 2012, 10:21:10 PM »
What are you trying to do?  Maybe theSwamp has a solution already posted somewhere.  You can search the Show Your Stuff area of xref stuff, as I have posted some items in there; Lisp and .Net.
Tim

I don't want to ' end-up ', I want to ' become '. - Me

Please think about donating if this post helped you.

BlackBox

  • King Gator
  • Posts: 3770
Re: Calling .net LispFunction while processing DBX
« Reply #9 on: October 26, 2012, 06:43:25 AM »
So is there a way to get the appropriate Database to GetObject() the ObjectId I supply when it came from a document opened in lisp via DBX?

I've not tested this myself with ObjectDBX, but in lieu of Application.DocumentManager.MdiActiveDocument Document Object to access the Database , you might consider using HostApplicationServices.WorkingDatabase instead.

Again, you've not posted any code, so it's hard to tell what other changes may be necessary.
"How we think determines what we do, and what we do determines what we get."

gile

  • Gator
  • Posts: 2520
  • Marseille, France
Re: Calling .net LispFunction while processing DBX
« Reply #10 on: October 26, 2012, 07:09:22 AM »
What about using Database.ReadDwgFile() .NET method instead of ObjectDBX ?
Speaking English as a French Frog

BlackBox

  • King Gator
  • Posts: 3770
Re: Calling .net LispFunction while processing DBX
« Reply #11 on: October 26, 2012, 07:44:37 AM »
What about using Database.ReadDwgFile() .NET method instead of ObjectDBX ?

Gile - Thank you for suggesting this!

Database.ReadDwgFile() may be exactly what I was after in order to successfully port one of my Civil 3D routines from Visual LISP/ObjectDBX to .NET
"How we think determines what we do, and what we do determines what we get."

CADDOG

  • Newt
  • Posts: 82
  • wishbonesr
Re: Calling .net LispFunction while processing DBX
« Reply #12 on: October 26, 2012, 01:13:47 PM »
What about using Database.ReadDwgFile() .NET method instead of ObjectDBX ?
That what I was saying I'd try first - kinda - more like a hybrid of the two.
I'm going to try two different ways...

First I'm going to shoot at opening the dwg by suppying the path\file and use ReadDwgFile() - which means I'm openign the file twice (ha).  Once in dbx and the other .net

Second I'm going to attempt COM...
But this is a transition.  I'll get to prompting, processing, iterating a drawing list in .net eventually.  Many of my batch processors were based on nested optional calls to dbx (process-current or select-files), and it will take some time to clean them up and modularize them to supply a list of files (strings) to lisp functions; Not to mention how many things I don't know about AutoCAD API vs. what I DO know about AutoLisp/VisualLisp.  My current intro attempt at making LispFunctions in .net was to provide functions that are near impossible to do in lisp (or just haven't been figured out yet - like obtaining a complete status on xref's as there's only so much you can get off of dxf 70 & 71) I'm not ready to convert entire programs into .net, Yet. 

I think I just picked the wrong project (which needs batching) to build my first .net LispFunction.  Would have worked out well, if I was only using in the current autocad session.

I've dropped this anyway, and gone back to what I know.  Will progress further the next go-around.

Thank you so much guys.  I appreciate the guidance and will be back for more.

TheMaster

  • Guest
Re: Calling .net LispFunction while processing DBX
« Reply #13 on: October 30, 2012, 09:47:25 AM »
I've already finished in lisp so I hope nobody spends too much more time looking at this one.
For historical purposes.  Here was the function.

......

//This one fails because the ename/ObjectId (of course) is not going to be the same with the same drawing in two different sessions.
//Handle is my only other option me thinks, but then I might have to make two different flavors, one for a handle and drawing, and the other for ObjectId in current drawing.
//I don't prefer to make handling Handles the default - I'd rather ObjectId's and avoid conversion/confusion.
//Would have to invent a way to detect if supplied var is ename or handle.  Or just try catch i guess??  Use an overload once the var type is discovered.  Also might need to cycle the drawings open in DocumentManager to avoid opening twice if it's already open in user session of autocad (non dbx).


As I'm sure you've already reconed, ObjectIds are database-specific and so are handles.

You can't identify an object in one database using an ObjectId or handle of an object in another database. In the case of a BlockTableRecord representing an xref, the only thing they have in common is the path of the xref'd drawing file.

However, you're jumping through a lot of hoops here, needlessly.

On the LISP side, you can open the database using ObjectDBX, get the vla-object of the AcadBlock representing the xref, and pass that to (vlax-vla-object->ename), and then just pass the result to your LispFunction, which will get the ObjectId of the AcadBlock/BlockTableRecord.

The ObjectId class has a Database property, that returns the containing database, and that's what you would use to access anything else in the same database. (vlax-vla-object->ename) along with the Database property of the ObjectId is also the key to solving the more general problem of passing a database that was opened via ObjectDBX in LISP or another ActiveX consumer, to managed code. You just pass the entity name of any object in that database, and the ObjectId that comes out on the managed side, gives you the containing Database.

« Last Edit: October 30, 2012, 09:59:31 AM by TT »

CADDOG

  • Newt
  • Posts: 82
  • wishbonesr
Re: Calling .net LispFunction while processing DBX
« Reply #14 on: October 30, 2012, 01:26:52 PM »
The ObjectId class has a Database property, that returns the containing database, and that's what you would use to access anything else in the same database. (vlax-vla-object->ename) along with the Database property of the ObjectId is also the key to solving the more general problem of passing a database that was opened via ObjectDBX in LISP or another ActiveX consumer, to managed code. You just pass the entity name of any object in that database, and the ObjectId that comes out on the managed side, gives you the containing Database.
There are times when even the solution is frustrating.  Fighting for hours, sometimes even days, while the simplest of properties and direct routes evade.

I think I love you man.   :kewl:

Seriously though; Knowing you can get to the object when in dbx opens the door for so many other things I wanted to do.

Thank you.

Code - C#: [Select]
  1. [LispFunction("cd:ename-xref-isresolved")]
  2. public bool Ename_xref_isResolved(ResultBuffer rb)
  3. {
  4.     if (rb == null)
  5.     { return false; }
  6.     TypedValue[] args = rb.AsArray();
  7.     if (args.Length > 1 || (LispDataType)args[0].TypeCode != LispDataType.ObjectId)
  8.     { return false; }
  9.     ObjectId ObjId = (ObjectId)args[0].Value;
  10.     using (Transaction tr = ObjId.Database.TransactionManager.StartTransaction())
  11.     {
  12.         try
  13.         {
  14.             BlockTableRecord btr = (BlockTableRecord)tr.GetObject(ObjId, OpenMode.ForRead, false);
  15.             if (btr.IsResolved)
  16.                 return true;
  17.         }
  18.         catch (System.Exception)
  19.         {
  20.             tr.Abort();
  21.             return false;
  22.         }
  23.     }
  24.     return false;
  25. }