.NET
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Calling DLL From Lisp

7 REPLIES 7
Reply
Message 1 of 8
Anonymous
626 Views, 7 Replies

Calling DLL From Lisp

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
7 REPLIES 7
Message 2 of 8
Anonymous
in reply to: Anonymous

Dale,
You need to set up your classes for COM interop in order to call them from
LISP this way.

Here is what I do:

Create an Interface that contains all of the members that you want to expose
to a COM client. Set its Guid and ComVisible attributes
[Guid("")]
[ComVisible(true)]

Create your class and have it implement your interface. Set these
attributes on the class.
[ClassInterface(ClassInterfaceType.None)]
[Guid("")]
[ProgId("")] //"Lab2.DynamicWindowsClass1"
[ComVisible(true)]

Make sure that your class has a public constructor that accepts no
arguments. This is the constructor that will be called when the class is
instantiated by the COM client. You can overload the constructor, but you
will only be able to call constructors with arguments from .NET consumers.

On your development machine you can set VS to register your assembly for COM
at compile time. You will need to have the installer handle COM
registration on other machines, or have them self register. I haven't gone
the self registering route, but I believe that Tony Tanzillo may have posted
some code on one of the groups showing an example.
--
Bobby C. Jones
http://www.acadx.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
Message 3 of 8
Anonymous
in reply to: Anonymous

Thanks Bobby. I'm brand new to .Net so I'll look into these topics. Any
chance of a sample?






"Bobby C. Jones" wrote in message
news:4948377@discussion.autodesk.com...
Dale,
You need to set up your classes for COM interop in order to call them from
LISP this way.

Here is what I do:

Create an Interface that contains all of the members that you want to expose
to a COM client. Set its Guid and ComVisible attributes
[Guid("")]
[ComVisible(true)]

Create your class and have it implement your interface. Set these
attributes on the class.
[ClassInterface(ClassInterfaceType.None)]
[Guid("")]
[ProgId("")] //"Lab2.DynamicWindowsClass1"
[ComVisible(true)]

Make sure that your class has a public constructor that accepts no
arguments. This is the constructor that will be called when the class is
instantiated by the COM client. You can overload the constructor, but you
will only be able to call constructors with arguments from .NET consumers.

On your development machine you can set VS to register your assembly for COM
at compile time. You will need to have the installer handle COM
registration on other machines, or have them self register. I haven't gone
the self registering route, but I believe that Tony Tanzillo may have posted
some code on one of the groups showing an example.
--
Bobby C. Jones
http://www.acadx.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
Message 4 of 8
Anonymous
in reply to: Anonymous

What type of value is used for the Guid?


"Bobby C. Jones" wrote in message
news:4948377@discussion.autodesk.com...
Dale,
You need to set up your classes for COM interop in order to call them from
LISP this way.

Here is what I do:

Create an Interface that contains all of the members that you want to expose
to a COM client. Set its Guid and ComVisible attributes
[Guid("")]
[ComVisible(true)]

Create your class and have it implement your interface. Set these
attributes on the class.
[ClassInterface(ClassInterfaceType.None)]
[Guid("")]
[ProgId("")] //"Lab2.DynamicWindowsClass1"
[ComVisible(true)]

Make sure that your class has a public constructor that accepts no
arguments. This is the constructor that will be called when the class is
instantiated by the COM client. You can overload the constructor, but you
will only be able to call constructors with arguments from .NET consumers.

On your development machine you can set VS to register your assembly for COM
at compile time. You will need to have the installer handle COM
registration on other machines, or have them self register. I haven't gone
the self registering route, but I believe that Tony Tanzillo may have posted
some code on one of the groups showing an example.
--
Bobby C. Jones
http://www.acadx.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
Message 5 of 8
Anonymous
in reply to: Anonymous

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
Message 6 of 8
Anonymous
in reply to: Anonymous

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
Message 7 of 8
Anonymous
in reply to: Anonymous

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
Message 8 of 8
Anonymous
in reply to: Anonymous

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

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

Autodesk DevCon in Munich May 28-29th


Autodesk Design & Make Report

”Boost