TheSwamp
Code Red => AutoLISP (Vanilla / Visual) => Topic started by: guohq on August 31, 2014, 09:07:20 AM
-
I create a project in vs2010 and the com interop is checked.
here is the code:
Public Class PointEx
Public Function GetPointZCoord(ByVal Pt As Object, ByRef ZCoord As Double) As Boolean
Try
If Pt Is Nothing OrElse Pt.ObjectName <> "AcDbPoint" Then
Return False
End If
Dim Coord() As Double = Pt.Coordinates()
ZCoord = Coord(2)
Return True
Catch ex As Exception
Return False
End Try
End Function
End Class
Then,I call the function with lisp in autocad:
(setq ptTool (vlax-create-object "VLispEx.PointEx"))
(setq Z 0)
(vlax-invoke ptTool 'GetPointZCoord (vlax-ename->vla-object (car (entsel))) Z)
(vlax-release-object ptTool)
At last,the value of param Z is still 0,it dosen't has any change.Can you tell me why?
-
Lisp (well AutoLisp) works the other way round. Instead of telling the function that its parameter is referencing something from outside, you tell the place where you call the function that the argument you're sending it needs to be "by reference". In Lisp this is rather referred to as sending the symbol name instead of the symbol's value. Also the function needs to work on the assumption (or test for) that the parameter is a symbol name instead of a value.
So when writing something like this in Lisp, you'd have done something like:(defun GetPointZCoord
(Pt ZCoord
/ Coord
) (and Pt
;Check if point object (setq Coord
(vlax-get Pt 'Coordinates
)) ;And get coordinates (= (type ZCoord
) 'Sym
) ;Check if ZCoord is passed in as a symbol name (set ZCoord
(nth 2 Coord
)) ;Check if Z can be set into symbol parameter )
)
Note when setting the value to the ZCoord parameter it's first checked to see if it is just a symbol name. Then it uses SET instead of SETQ, i.e. use the symbol name inside the variable instead of quoting the variable's name and then setting that. Now when calling that function, you need to quote the "variable" passed in as the ZCoord argument - i.e. you're quoting it outside the function which is going to set it.
Here's a sample from ACad's command-line:Command: (GetPointZCoord (vlax-ename->vla-object (car (entsel))) 'Z)
Select object: T
Command: !Z
2000.0
Notice the ' prefix to Z - short hand for writing (quote Z).
Now, you're working from the DotNet side. If what you're after is to set the argument in Lisp from within DotNet - that's a whole new ballgame. Unfortunately ADesk's interaction between DotNet and Lisp do not cater for these things - all arguments passed in to DotNet is converted to a ResultBuffer list and is always only passed in as ByValue. Not to mention, DotNet doesn't accept vla-objects as arguments to its LispFunction methods - you'd simply need to send it the ename as obtained from (car (ensel)) instead.
To get around this issue though you can "simulate" something like a ByRef parameter, by expecting a string naming the symbol in the ZCoord parameter's place. This you do using the document object's SetLispSymbol method - see an example use here: http://adndevblog.typepad.com/autocad/2014/08/set-or-get-lisp-symbol-in-net.html
Edit: Sorry I see you're making Com-interop. Well perhaps this works, just call that function in the same way you'd call it if it was written in Lisp as above - i.e. prefix the Z value with a quote. E.g. that's how you'd call the standard ActiveX GetBoundingBox method:After which MinCoord would contain the "bottom left 3d point as a safearray of variants, as would the MaxCoord contain that of the top-right.
If the same happens for your custom Com exported function I've never really tested. Perhaps you've found a better way to get this working than that convoluted SetLispSymbol idea.
-
Although the problem is not resolved,thank you all the same.
-
Although the problem is not resolved,thank you all the same.
So you mean it doesn't work if you do this:
What if you go with the vlax-invoke-method call instead:
I've seen some strange stuff happen due to weird differences between those two.
Unfortunately if this simply "will not work" you're stuck with rather exporting the function as a LispFunction from the DotNet side instead of going through ActiveX.
Also you haven't mentioned how you made the VB code you have COM visible. Did you follow the steps in section 1 of this tut?
https://www.simple-talk.com/dotnet/visual-studio/build-and-deploy-a-.net-com-assembly/
Most important you have to make a Com-Visible Interface, which your class then needs to implement. And also you'd need to register it with proper GUIDs.
-
This function 'vlax-invoke-method‘ achieve my goals! Thank you! :evil:
-
This function 'vlax-invoke-method‘ achieve my goals! Thank you! :evil:
Awesome, glad you got it sorted!