I have the following code for testing Autocad automation, it should draw a circle in model space.
This wont assemble unless i comment out the actual drawing function
invoke dm(pIModelSpace,IAcadModelSpace,AddCircle),addr pICircle,AcadPnt,Radius
If not commented out, i get the errors regarding the above line:
in autocadc.inc there is
so i don't get it. Where's the mismatch?
Does the SAFEARRAY / VARIANT init look right, i'm not too sure about them? Anyway, even if they are not correct, that should not affect assembling?
.:EDIT: by NaN to add 'CODE' blocks. Janne, edit your post to learn what I did ;)
F3DPOINT STRUCT
X real8 ?
Y real8 ?
Z real8 ?
F3DPOINT ENDS
InitAcad proc
LOCAL pIAcadDocument:dword
LOCAL pIModelSpace:dword
LOCAL pICircle:dword
LOCAL AcadPnt:VARIANT
LOCAL AcadXYZ:SAFEARRAY
LOCAL Radius:REAL8
LOCAL XYZ:F3DPOINT
LOCAL OwID:dword
finit
fld1;just for testing X=Y=Z=Radius=1
fst Radius
fst XYZ.X
fst XYZ.Y
fstp XYZ.Z
mov AcadXYZ.cDims,1
mov AcadXYZ.fFeatures,1
mov AcadXYZ.cbElements,8
mov AcadXYZ.cLocks,0
lea eax,XYZ
mov AcadXYZ.pvData,eax
mov AcadXYZ.rgsabound.lLbound,0
mov AcadXYZ.rgsabound.cElements,3
mov AcadPnt.vt,VT_R8 or VT_ARRAY
mov AcadPnt.wReserved1,0
mov AcadPnt.wReserved2,0
mov AcadPnt.wReserved3,0
lea eax,AcadXYZ
mov AcadPnt.parray,eax
invoke CoInitialize, NULL
invoke CoCreateInstance, ADDR CLSID_AcadApplication, NULL, CLSCTX_ALL,\
addr IID_IAcadApplication, addr pIAcadApplication
PrintHex eax,"ACAD CoCreateInstance ret value"
invoke vf(pIAcadApplication, IAcadApplication, put_Visible), TRUE
PrintHex pIAcadDocument
invoke vf(pIAcadApplication, IAcadApplication, get_ActiveDocument), addr pIAcadDocument
PrintHex pIAcadDocument
PrintHex pIModelSpace
invoke dm(pIAcadDocument, IAcadDocument, get_ModelSpace), addr pIModelSpace
PrintHex pIModelSpace
PrintHex OwID
invoke dm(pIModelSpace, IAcadModelSpace, get_OwnerID), addr OwID ;this seems to work
PrintHex OwID
invoke dm(pIModelSpace, IAcadModelSpace, AddCircle), addr pICircle,AcadPnt,Radius
invoke CoUninitialize
ret
InitAcad endp
This wont assemble unless i comment out the actual drawing function
invoke dm(pIModelSpace,IAcadModelSpace,AddCircle),addr pICircle,AcadPnt,Radius
If not commented out, i get the errors regarding the above line:
error A2114: INVOKE argument type mismatch : argument : 5
error A2114: INVOKE argument type mismatch : argument : 4
error A2114: INVOKE argument type mismatch : argument : 3
in autocadc.inc there is
DEFINE_DISPMETHOD IAcadModelSpace , AddCircle, 060Ah, METHOD, VT_BYREF OR VT_USERDEFINED, VT_VARIANT,VT_R8
so i don't get it. Where's the mismatch?
Does the SAFEARRAY / VARIANT init look right, i'm not too sure about them? Anyway, even if they are not correct, that should not affect assembling?
.:EDIT: by NaN to add 'CODE' blocks. Janne, edit your post to learn what I did ;)
changed
to
,now the damn thing works.
I thought that i can see the order of the parameters from
but apparently not?
invoke dm(pIModelSpace, IAcadModelSpace, AddCircle), addr pICircle, AcadPnt, Radius
to
invoke dm(pIModelSpace, IAcadModelSpace, AddCircle), AcadPnt, Radius, addr pICircle
,now the damn thing works.
I thought that i can see the order of the parameters from
DEFINE_DISPMETHOD IAcadModelSpace , AddCircle, 060Ah, METHOD, VT_BYREF OR VT_USERDEFINED, VT_VARIANT,VT_R8
but apparently not?
1) I hope you dont mind, but I edited you posts such that i can better read and understand your source and problem. Basically i added "code" blocks.
2) I find you problem odd. And not really sure why, but i suspect that it has alot to do with the dm() macro and sustaining source for it. A while back, burried somewhere in this forum, Japheth and I had a very long discussion on the eventual need and development of the dm() macro. However, at the end of the day, Japheth had his own views on how it should run (code wise), and I had my own. Im not saying his is wrong, but I dont *know* it, because i dont use it.
My version is close to his, but different in how it sets up the arguments to methods, and then calls the invoke method. I have a source file called "Disphelp.inc" does alot of the dirty work of dealing with variants for Invoke methods. I have attached the DispHelp.inc file that i use with his COMView outputs, use it if you like.
It will generate the variants for you, all you need to do is call the first "MakeInvokeString" to specify the arguments a method may have (number, flowed by the VT_* types for each argument). Then in the dm() invoke call, the first two arguments are the return type, and return value pointer (they can be NULL if ther is no return). All other arguments are the values to stuff into the variant's, as prescribed in the above "MakeInvokeString" call. My function here will use the stack to allocated a bunch of variants as needed and fill them with your arguments, and type befor calling the Invoke method.
With this source included into a project here is how i would have done your source:
As well it shows you how to use the SafeArrays ;)
Hope this is some help to you!
:alright:
NaN
2) I find you problem odd. And not really sure why, but i suspect that it has alot to do with the dm() macro and sustaining source for it. A while back, burried somewhere in this forum, Japheth and I had a very long discussion on the eventual need and development of the dm() macro. However, at the end of the day, Japheth had his own views on how it should run (code wise), and I had my own. Im not saying his is wrong, but I dont *know* it, because i dont use it.
My version is close to his, but different in how it sets up the arguments to methods, and then calls the invoke method. I have a source file called "Disphelp.inc" does alot of the dirty work of dealing with variants for Invoke methods. I have attached the DispHelp.inc file that i use with his COMView outputs, use it if you like.
It will generate the variants for you, all you need to do is call the first "MakeInvokeString" to specify the arguments a method may have (number, flowed by the VT_* types for each argument). Then in the dm() invoke call, the first two arguments are the return type, and return value pointer (they can be NULL if ther is no return). All other arguments are the values to stuff into the variant's, as prescribed in the above "MakeInvokeString" call. My function here will use the stack to allocated a bunch of variants as needed and fill them with your arguments, and type befor calling the Invoke method.
With this source included into a project here is how i would have done your source:
F3DPOINT STRUCT
X real8 ?
Y real8 ?
Z real8 ?
F3DPOINT ENDS
.data
AcadXYZ F3DPOINT <1.0, 2.0, 3.0>
.code
; Build a SAFEARRAY of R8 numbers
invoke SafeArrayCreateVector, VT_R8, 0, 3
mov hSafeArray, eax
xor eax, eax
mov counter, eax
[b]lea eax, AcadXYZ[/b]
mov countdata, eax
.while (counter != 3)
invoke SafeArrayPutElement, hSafeArray, addr counter, countdata
inc counter
add countdata, 8
.endw
; Your source transcribed...
invoke CoInitialize, NULL
invoke CoCreateInstance, ADDR CLSID_AcadApplication, NULL, CLSCTX_ALL,\
addr IID_IAcadApplication, addr pIAcadApplication
invoke vf(pIAcadApplication, IAcadApplication, put_Visible), TRUE
invoke vf(pIAcadApplication, IAcadApplication, get_ActiveDocument), addr pIAcadDocument
;OLD: invoke dm(pIAcadDocument, IAcadDocument, get_ModelSpace), addr pIModelSpace
invoke MakeInvokeString, 0
invoke dm(pIAcadDocument, IAcadDocument, get_ModelSpace), VT_DISPATCH, addr pIModelSpace
;OLD: invoke dm(pIModelSpace, IAcadModelSpace, get_OwnerID), addr OwID
invoke MakeInvokeString, 0
invoke dm(pIModelSpace, IAcadModelSpace, get_OwnerID), VT_DISPATCH, addr OwID
;OLD: invoke dm(pIModelSpace, IAcadModelSpace, AddCircle), addr pICircle,AcadPnt,Radius
;DEFINE_DISPMETHOD IAcadModelSpace , AddCircle, 060Ah, METHOD, VT_BYREF OR VT_USERDEFINED,
invoke MakeInvokeString, 2, VT_ARRAY or VT_R8, VT_R8
invoke dm(pIModelSpace, IAcadModelSpace, get_OwnerID), VT_DISPATCH, addr pICircle, [b]hSafeArray[/b], Radius
[b]invoke SafeArrayDestroy, hSafeArray[/b]
invoke CoUninitialize
As well it shows you how to use the SafeArrays ;)
Hope this is some help to you!
:alright:
NaN
Oops, for got to post the source ;)
NaN, thanks a lot for all the info.
Hi guys,
let me mention my view as well. This problem is not an error in macro dm(), it's due to some misunderstanding.
Janne, this DEFINE_DISPMETHOD macro has following parameters:
If you look in typeinfo for IDispatch interface IAcadModelSpace you will see method AddCircle defined as
[] Ptr IAcadCircle AddCircle ( Center:Variant, Radius:R8 )
So DEFINE_DISPMETHOD is correct in my eyes.
macro dm() in fact expects parameters in standard COM format, that is
1. the method itself does return a HResult (in eax)
2. "return type" from IDispatch interface will be last parameter and converted to a pointer to this type
There exists a typeinfo (somewhat hidden in comview, but you may find it) with type TKIND_INTERFACE (not TKIND_DISPATCH), where this parameter structure could be seen:
[] HResult AddCircle ( Center:Variant, Radius:R8, pCircle:Ptr Ptr IAcadCircle )
And this parameter structure is used for the call, that is, this function has in fact 3 parameters (+ "this"),
and returntype comes last.
Japheth
let me mention my view as well. This problem is not an error in macro dm(), it's due to some misunderstanding.
Janne, this DEFINE_DISPMETHOD macro has following parameters:
DEFINE_DISPMETHOD Interfacename, Methodname, DISPID, InvokeKind, return type, parameter1 type, parameter2 type,...
If you look in typeinfo for IDispatch interface IAcadModelSpace you will see method AddCircle defined as
[] Ptr IAcadCircle AddCircle ( Center:Variant, Radius:R8 )
So DEFINE_DISPMETHOD is correct in my eyes.
macro dm() in fact expects parameters in standard COM format, that is
1. the method itself does return a HResult (in eax)
2. "return type" from IDispatch interface will be last parameter and converted to a pointer to this type
There exists a typeinfo (somewhat hidden in comview, but you may find it) with type TKIND_INTERFACE (not TKIND_DISPATCH), where this parameter structure could be seen:
[] HResult AddCircle ( Center:Variant, Radius:R8, pCircle:Ptr Ptr IAcadCircle )
And this parameter structure is used for the call, that is, this function has in fact 3 parameters (+ "this"),
and returntype comes last.
Japheth
Japheth, im sorry if I offended you. It was not my goal. I only ment to explain that what i can provide *is* going to be different from what you have provided for the dm() macro. Hopefully no offense to you, but i choose to use my stack based calling proceedure instead of your alternate (forget how it works at this point, sorry).
:NaN:
:NaN:
NaN, its ok, I didnt feel insulted
Japheth
Japheth