Terrific, thanks again Tony.
"Tony Tanzillo" wrote in message
news:4949276@discussion.autodesk.com...
Hi Dale - See the thread titled:
Passing arguments and returning values with .NET and LISP
--
http://www.caddzone.com
AcadXTabs: MDI Document Tabs for AutoCAD 2004/2005/2006
http://www.acadxtabs.com
"Dale Levesque" wrote in message
news:4949143@discussion.autodesk.com...
THANKS Tony. I did not realize that there was a related thread with posted
code though. I've searched through this newsgroup without any luck. All I
need is the bare bones code that will allow the lisp routine to call the
function stored in the DLL.
Dale
"Tony Tanzillo" wrote in message
news:4948672@discussion.autodesk.com...
Hi Dale - If you're following the related thread where
I posted code showing a simple COM server, there's
a few things I should point out.
The first is that it is, by design, a "bare-minimal"
implementation of COM-callable code, intended
for exposing code for _private_ consumption, from
visual lisp.
If the exposed code is 'private' (meaning it is not
intended for general consumption by any consumer,
but rather, only your own consumer), the lack of a
published interface serves a good purpose, which is
to make the COM component non-public. That's a
good thing, believe it or not.
If you are developing a COM-callable component
for public consumption by others, then as another
response mentions, you have to follow the pattern
that is gernally used to expose managed code via
COM, which involves creating and exposing a COM
interface; using ClassInterfaceType.None, to hide
base class members that are visible to COM; and
registering the library using an installer or regasm.
But, for private consumption by only your Visual
LISP code (which presumably already knows what
methods and properties your COM server exposes
and hence, does not require a published, public
interface), and to inhibit use of it by others, the
bare-minimal implementation like what I showed
will work, and will help to keep unwanted parties
from calling your code.
Another issue is that if your COM component uses
the AutoCAD interop libraries, it cannot be loaded
as a COM server into any COM client not running in
AutoCAD's process space. But, any Visual LISP app
can call it, provided they know what methods and
properties it exposes (and that's the fundamental
purpose of having a public interface).
So, the usual pattern for exposing .NET code to
COM for general or 'public' consumption does not
nessarily apply for private connectivity between
VisualLISP and managed code. In fact, it can pose
a security problem.
Now that we've got that out of the way, The one
thing I failed to touch on earlier, is registration.
Building an installer is not something that I
generally do if it is only for the purpose of
registering a COM server for private use only
by my own code. Hence, setting your project
to register your assembly for COM interop is
not terribly useful for deployment purposes,
only for the development cycle. Also, if your
assembly consumes COM components, like the
AutoCAD COM Interop, it must be signed.
So, here is a way to make a COM component that
uses the AutoCAD interop libraries self-registering
when the assembly is loaded into AutoCAD using
NETLOAD (sorry, this is C#):
// Dependencies:
using System;
using System.Reflection;
using System.Runtime.InteropServices;
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.ApplicationServices;
// Helper property:
private Document ActiveDoc
{
get
{
return Autodesk.AutoCAD.ApplicationServices.
Application.DocumentManager.MdiActiveDocument;
}
}
// IExtensionApplication.Initialize() implementation:
// The code below will register the containing assembly
// for COM interop when the assembly is loaded into
// AutoCAD, via NETLOAD (note: it will do nothing when
// the containing assembly is loaded as a COM server
// by Windows):
public void Initialize()
{
// we only want to do this when the assembly is
// explicitly loaded by the user using NETLOAD:
if( ActiveDoc.CommandInProgress == "NETLOAD" )
{
new RegistrationServices().RegisterAssembly(
Assembly.GetExecutingAssembly(),
AssemblyRegistrationFlags.SetCodeBase);
}
}
Implementing IExtensionApplication on a COM class
may not be a good practice, because AutoCAD will
create and hold an instance of that class when the
assembly that contains it is loaded. Instead, create
another class that's invisible to COM, and implement
IExtensionApplication on that class.
--
http://www.caddzone.com
AcadXTabs: MDI Document Tabs for AutoCAD 2004/2005/2006
http://www.acadxtabs.com
"Dale Levesque" wrote in message
news:4948313@discussion.autodesk.com...
I have the following Class Library called Lab2. I compile and load it into
AutoCAD 2006 using netload. I can type the command "getDistance" and it
works properly.
If I try to call it from Lisp using the following code it crashes when the
vla-GetInterfaceObject function is called. Any suggestions?
(setq $acad (vlax-get-acad-object))
(setq vbstrcls (vla-GetInterfaceObject $acad
"Lab2.DynamicWindowsClass1"))
(setq out (vlax-invoke-method vbstrcls "getDistance"))
out
(vlax-release-object vbstrcls)
(vlax-release-object $acad)
Imports Autodesk.AutoCAD.Runtime
Imports Autodesk.AutoCAD.ApplicationServices
Imports Autodesk.AutoCAD.EditorInput
Public Class DynamicWindowsClass1
' Define command 'Asdkcmd1'
_
Public Function Asdkcmd1()
Dim prPointOptions As PromptPointOptions = New PromptPointOptions("Select a
point")
Dim prPointRes As PromptPointResult
Dim ed As Editor = Application.DocumentManager.MdiActiveDocument.Editor
prPointRes = ed.GetPoint(prPointOptions)
If prPointRes.Status <> PromptStatus.OK Then
Return Nothing
End If
ed.WriteMessage("You selected point " & prPointRes.Value.ToString())
End Function
' Define command 'Asdkcmd1'
_
Public Function Asdkcmd2()
Dim ed As Editor = Application.DocumentManager.MdiActiveDocument.Editor
Dim prDistOptions As PromptDistanceOptions = New PromptDistanceOptions("Find
Distance, Select First Point:")
Dim prdistRes As PromptDoubleResult
prdistRes = ed.GetDistance(prDistOptions)
If prdistRes.Status <> PromptStatus.OK Then
Return Nothing
End If
ed.WriteMessage("The distance is " & prdistRes.Value.ToString())
End Function
End Class