AutoHotkey Homepage AutoHotkey Community
Let's help each other out
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

COM Helper
Goto page Previous  1, 2, 3 ... 8, 9, 10, 11  Next
 
This topic is locked: you cannot edit posts or make replies.    AutoHotkey Community Forum Index -> Scripts & Functions
View previous topic :: View next topic  
Author Message
tfcahm



Joined: 20 May 2007
Posts: 48

PostPosted: Wed Jul 04, 2007 2:55 am    Post subject: Reply with quote

Quote:
OK, I'd like to leave it to you.
Alright. May be a few days before I get to it. Obviously it will be more complicated than the current function.
Quote:
first byte of the allocated varg will be erased
Got it. Thanks!
Quote:
I'm not sure if it's AHK's problem.
I'm suspecting that BookCat may have a bug to manage a buffer, as I think that the original script using the VTable interface would have worked already otherwise.
Could be. BookCAT's author seems very responsive, so with a good definition of the problem I expect it will get fixed.
Back to top
View user's profile Send private message
tfcahm



Joined: 20 May 2007
Posts: 48

PostPosted: Sat Jul 07, 2007 3:12 pm    Post subject: Reply with quote

Sean,

The problems with memory errors, and other strange goings-on in my script are resolved. The guy who provided the original Perl code came up with the answer. The ByRef strings need to be cleared with a VariantClear dll call. Seems logical there should be a VariantInit to go with it, but this works flawlessly as is. The code below is an updated version of the code you posted above. It is also has the offsets modified to work with the July 5 version of Invoke(). Thanks again for originally posting this code as it was the key to me being able to move forward with my own.

Code:
#Include CoHelper.ahk

CoInitialize()
pds := ActiveXObject("BookCAT.DataServer")

sXSLTemplate := "BookList.xsl"
sFilter      := "Author=John Grisham"
sFilename    := ""
sRecordset   := ""
bStripLinks  := False

pXSLTemplate := SysAllocString(sXSLTemplate)
pFilter      := SysAllocString(sFilter)
pFilename    := SysAllocString(sFilename)
pRecordset   := SysAllocString(sRecordset)

VarSetCapacity(var, 88, 0)
var := Chr(5)
NumPut(8|0x4000, var, 1), NumPut(&var+81, var, 9)
NumPut(8|0x4000, var,17), NumPut(&var+84 ,var,25)
NumPut(11,var, 33), NumPut(-bStripLinks, var, 41, "short")
NumPut(8, var, 49), NumPut(pFilter     , var, 57)
NumPut(8, var, 65), NumPut(pXSLTemplate, var, 73)
NumPut(pRecordset, var, 81), NumPut(pFilename, var, 85)

nResult := Invoke(pds, "GenerateHTML", &var)
Unicode2Ansi(pstr1 := NumGet(var, 81), sRecordset)
Unicode2Ansi(pstr2 := NumGet(var, 85), sFilename)

SysFreeString(pXSLTemplate)
SysFreeString(pFilter)
DllCall("oleaut32.dll\VariantClear","UInt",pFilename)
DllCall("oleaut32.dll\VariantClear","UInt",pRecordset)

; do other stuff...

Release(pds)
CoUninitialize()

MsgBox, % "GenerateHtml`n Filename: " . sFilename . "`n Recordset: " . sRecordset


I would be interested in using COM event if added to CoHelper. CoHelper and the example scripts you've shared are a great asset. Don't be detered by those who don't want to take the time to learn it. Every one of the example codes teaches something new. It took me a while to see how it all goes together, but that effort is paying off now. Thanks again for CoHelper, and for your example scripts.
Back to top
View user's profile Send private message
Sean



Joined: 12 Feb 2007
Posts: 2462

PostPosted: Sat Jul 07, 2007 5:26 pm    Post subject: Reply with quote

tfcahm wrote:
The problems with memory errors, and other strange goings-on in my script are resolved.

Nice!

Quote:
The guy who provided the original Perl code came up with the answer. The ByRef strings need to be cleared with a VariantClear dll call.

That's a bit strange. pFilename and pRecordset are not variant themselves...
Anyway, what VariantClear does in this case is to SysFreeString on pFilename and pRecordset, I beleive. Looks like I forgot to do that ...

Code:
#Include CoHelper.ahk

CoInitialize()
pds := ActiveXObject("BookCAT.DataServer")

sXSLTemplate := "BookList.xsl"
sFilter      := "Author=John Grisham"
sFilename    := ""
sRecordset   := ""
bStripLinks  := False

pXSLTemplate := SysAllocString(sXSLTemplate)
pFilter      := SysAllocString(sFilter)
pFilename    := SysAllocString(sFilename)
pRecordset   := SysAllocString(sRecordset)

VarSetCapacity(var, 88, 0)
var := Chr(5)
NumPut(8|0x4000, var, 1), NumPut(&var+81, var, 9)
NumPut(8|0x4000, var,17), NumPut(&var+84 ,var,25)
NumPut(11,var, 33), NumPut(-bStripLinks, var, 41, "short")
NumPut(8, var, 49), NumPut(pFilter     , var, 57)
NumPut(8, var, 65), NumPut(pXSLTemplate, var, 73)
NumPut(pRecordset, var, 81), NumPut(pFilename, var, 85)

nResult := Invoke(pds, "GenerateHTML", &var)
Unicode2Ansi(pstr1 := NumGet(var, 81), sRecordset)
Unicode2Ansi(pstr2 := NumGet(var, 85), sFilename)

SysFreeString(pXSLTemplate)
SysFreeString(pFilter)
DllCall("oleaut32.dll\VariantClear","UInt",pFilename)
DllCall("oleaut32.dll\VariantClear","UInt",pRecordset)

; do other stuff...

Release(pds)
CoUninitialize()

MsgBox, % "GenerateHtml`n Filename: " . sFilename . "`n Recordset: " . sRecordset


Quote:
It is also has the offsets modified to work with the July 5 version of Invoke().

You really managed well with the unnatural 1byte offset shift. This is the best I can do atm without taking the full route of the dispatch interface.
But, I think it's better than the previous one like varg:=DispParams(num, varg, ...), as it would be hidden from the scene mostly, like:

Code:
VarSetCapacity(ref, 8), NumPut(pFilename, ref, 0), NumPut(pRecordset, ref, 4)
nResult := Invoke(pds, "GenerateHTML", DispParams(varg, 8, pXSLTemplate, 8, pFilter, 11, -bStripLinks, 8|0x4000, &ref, 8|0x4000, &ref+4))
Unicode2Ansi(pstr1 := NumGet(ref, 0), sFilename)
Unicode2Ansi(pstr2 := NumGet(ref, 4), sRecordset)


Quote:
I would be interested in using COM event if added to CoHelper. CoHelper and the example scripts you've shared are a great asset.

Maybe I can PM you the code later. Actually, it can be achieved without the long detour, for many cases. However, it's not 100% guaranteed. To make it work in any cases forced to take very tedious steps. I'm thinking about currently if there is any way to make it simpler.
And, thank you for the warm words!
Back to top
View user's profile Send private message
tfcahm



Joined: 20 May 2007
Posts: 48

PostPosted: Sat Jul 07, 2007 6:39 pm    Post subject: Reply with quote

Sean wrote:
That's a bit strange. pFilename and pRecordset are not variant themselves...
Anyway, what VariantClear does in this case is to SysFreeString on pFilename and pRecordset, I beleive. Looks like I forgot to do that ...
Actually, you did have SysFreeString on pFilename and pRecordset. In this case that apparently did not free them.

Quote:
You really managed well with the unnatural 1byte offset shift. This is the best I can do atm without taking the full route of the dispatch interface.
But, I think it's better than the previous one like varg:=DispParams(num, varg, ...), as it would be hidden from the scene mostly, like:

Code:
VarSetCapacity(ref, 8), NumPut(pFilename, ref, 0), NumPut(pRecordset, ref, 4)
nResult := Invoke(pds, "GenerateHTML", DispParams(varg, 8, pXSLTemplate, 8, pFilter, 11, -bStripLinks, 8|0x4000, &ref, 8|0x4000, &ref+4))
Unicode2Ansi(pstr1 := NumGet(ref, 0), sFilename)
Unicode2Ansi(pstr2 := NumGet(ref, 4), sRecordset)
Nice! I hadn't gone back to figure out how to do that using DispParams() yet. Thanks for the example.

Quote:
Maybe I can PM you the code later.
Much appreciated. No rush, I'm not quite ready for it anyway.
Back to top
View user's profile Send private message
Sean



Joined: 12 Feb 2007
Posts: 2462

PostPosted: Sun Jul 08, 2007 4:02 am    Post subject: Reply with quote

tfcahm wrote:
Actually, you did have SysFreeString on pFilename and pRecordset. In this case that apparently did not free them.

Then, I got the feeling that SysFreeString on ByRef parameters in this case should not be applied, may be handled by BookCat itself.
So, simply removing those lines might cure the symptom.

Quote:
Nice! I hadn't gone back to figure out how to do that using DispParams() yet. Thanks for the example.

I think it can be simplified a bit further.

Code:
VarSetCapacity(ref, 8)
nResult := Invoke(pds, "GenerateHTML", DispParams(varg, 8, pXSLTemplate, 8, pFilter, 11, -bStripLinks, 8|0x4000, NumPut(pFilename, ref, 0)-4, 8|0x4000, NumPut(pRecordset, ref, 4)-4))
Unicode2Ansi(pstr1 := NumGet(ref, 0), sFilename)
Unicode2Ansi(pstr2 := NumGet(ref, 4), sRecordset)
Back to top
View user's profile Send private message
tfcahm



Joined: 20 May 2007
Posts: 48

PostPosted: Sun Jul 08, 2007 5:28 am    Post subject: Reply with quote

Quote:
Then, I got the feeling that SysFreeString on ByRef parameters in this case should not be applied, may be handled by BookCat itself.
So, simply removing those lines might cure the symptom.

Brilliant! That works. Mystery solved. Guess the VariantClear was acting as a no-op in this case.
Back to top
View user's profile Send private message
erictheturtle



Joined: 27 Jun 2007
Posts: 101
Location: California

PostPosted: Sat Jul 14, 2007 4:00 pm    Post subject: Reply with quote

Hi Sean,

I wanted to ask you what the purpose of the GetIDispatch() function is in COMHelper.ahk.

Sudo code
Code:
GetIDispatch(ppv)
{
   ppv->GetTypeInfoCount(&cti)
   if (!cti)
      return
   ppv->GetTypeInfo(0, LCID, &pti)
   pti->GetTypeAttr(&pattr)
   ppv->QueryInterface(pattr->guid, &pdisp)
   pti->ReleaseTypeAttr(pattr)
   pti->Release()
   if (pdisp)
      ppv->Release()
   return pdisp
}

I found similar code here with the explaination of "Try to QueryInterface a COM pointer to the 'most useful' interface" and "find the interface marked as default". What advantages do you get from performing this step over just using the original IDispatch ppv?
_________________
-m35
Back to top
View user's profile Send private message
Sean



Joined: 12 Feb 2007
Posts: 2462

PostPosted: Sat Jul 14, 2007 10:13 pm    Post subject: Reply with quote

erictheturtle wrote:
What advantages do you get from performing this step over just using the original IDispatch ppv?

It's redundant mostly. So, I didn't add it to ActiveXObject etc at first, but decided to add it later to not cause a confusion as it would do no harm anyway, just superfluous.
If a COM server resides in another process and you're going to use VTBL interface of it, then this step is necessary.
Back to top
View user's profile Send private message
Sean



Joined: 12 Feb 2007
Posts: 2462

PostPosted: Thu Jul 26, 2007 5:00 am    Post subject: Reply with quote

Sean wrote:
tfcahm wrote:
I really like this. If you don't do it first, I'd like to extend it to handle BYREFs.
OK, I'd like to leave it to you.

OK, I implemented VT_BYREF too in Invoke_(). So, please test it:

Code:
#Include CoHelper.ahk

sXSLTemplate := "BookList.xsl"
sFilter      := "Author=John Grisham"
bStripLinks  := False

CoInitialize()
pds := ActiveXObject("BookCAT.DataServer")
nResult := Invoke_(pds, "GenerateHTML", 8, sXSLTemplate, 8, sFilter, 11, bStripLinks, 8|0x4000, "", 8|0x4000, "")
sFilename  := _TEMP_VT_BYREF_4
sRecordset := _TEMP_VT_BYREF_5
Release(pds)
CoUninitialize()
MsgBox, % "GenerateHtml`n Filename: " . sFilename . "`n Recordset: " . sRecordset


The returned result will be saved in the global variables _TEMP_VT_BYREF_%A_Index%, where the index is the argument's position in the function.
Back to top
View user's profile Send private message
tfcahm



Joined: 20 May 2007
Posts: 48

PostPosted: Thu Jul 26, 2007 6:37 am    Post subject: Reply with quote

Sean wrote:
OK, I implemented VT_BYREF too in Invoke_().
Wow...unexpected. Thanks!

It runs perfectly as you wrote it above, but strangely it does not work properly as a function. The values for _TEMP_VT_BYREF_n are blank. The GenerateHTML method in BookCAT runs properly and returns the correct nResult, so the only issue is the blank _TEMP_VT_BYREF_ values. I used edit 37 of CoHelper for this test.
Code:
#Include CoHelper.ahk
nResult := GenHTML()
ExitApp

GenHTML() {
  sXSLTemplate := "BookList.xsl"
  sFilter      := "Author=John Grisham"
  bStripLinks  := False
  CoInitialize()
  pds := ActiveXObject("BookCAT.DataServer")
  nResult := Invoke_(pds, "GenerateHTML", 8, sXSLTemplate, 8, sFilter, 11, bStripLinks, 8|0x4000, "", 8|0x4000, "")
  sFilename  := _TEMP_VT_BYREF_4
  sRecordset := _TEMP_VT_BYREF_5
  Release(pds)
  CoUninitialize()
  MsgBox, % "GenerateHtml`n Filename: " . sFilename . "`n Recordset: " . sRecordset
  Return nResult
}
Back to top
View user's profile Send private message
Sean



Joined: 12 Feb 2007
Posts: 2462

PostPosted: Thu Jul 26, 2007 8:49 am    Post subject: Reply with quote

tfcahm wrote:
It runs perfectly as you wrote it above, but strangely it does not work properly as a function. The values for _TEMP_VT_BYREF_n are blank.

_TEMP_VT_BYREF_%A_Index% is dynamically generated global variables inside Invoke_(). So, if you want to refer it inside functions, you have to declare them as Global. In this case, add the following at the start of the function:

Code:
Global _TEMP_VT_BYREF_4, _TEMP_VT_BYREF_5


PS. To me, there is an unclear point with VT_BYREF parameters.
Namely, still can expect type-coercions with VT_BYREF parameters?
Do you know of an app which uses other than bstr as ByRef?
I mean, it expects VT_R8|VT_BYREF, but we can specify it with VT_BSTR|VT_BYREF.
Then, OLE manger correctly type-coerced it and give to the function.
If so, how about the returned values? Will it be VT_R8 or VT_BSTR?
Back to top
View user's profile Send private message
erictheturtle



Joined: 27 Jun 2007
Posts: 101
Location: California

PostPosted: Thu Jul 26, 2007 12:57 pm    Post subject: Reply with quote

In my tests with the home-made COM object, I had a method like this
Code:
Public Sub RefArgs(ByRef str As String, ByRef i As Integer)
    str = "return a string"
    i = 4444
End Sub


When I Invoked this method with VT_BYREF|VT_BSTR and VT_BYREF|VT_I4, it failed saying the integer argument could not be coerced. When I changed the parameter to be "ByRef i as Long", then the Invoke succeeded. This let me to conclude that Invoke does not perform type coercion on ByRef parameters.
_________________
-m35
Back to top
View user's profile Send private message
tfcahm



Joined: 20 May 2007
Posts: 48

PostPosted: Thu Jul 26, 2007 2:05 pm    Post subject: Reply with quote

Sean wrote:
_TEMP_VT_BYREF_%A_Index% is dynamically generated global variables inside Invoke_().
I completely missed that...working too late. Thanks.

Sean wrote:
Do you know of an app which uses other than bstr as ByRef?
Nero has some ByRef as Variants. I haven't tried it.
Back to top
View user's profile Send private message
Sean



Joined: 12 Feb 2007
Posts: 2462

PostPosted: Thu Jul 26, 2007 10:51 pm    Post subject: Reply with quote

erictheturtle wrote:
When I Invoked this method with VT_BYREF|VT_BSTR and VT_BYREF|VT_I4, it failed saying the integer argument could not be coerced. When I changed the parameter to be "ByRef i as Long", then the Invoke succeeded. This let me to conclude that Invoke does not perform type coercion on ByRef parameters.

Thanks for the test. I first added the coercion code into the return value of ByRef code without thinking, but after thinking it started to make little sense to me, so I removed it immediately.
Back to top
View user's profile Send private message
polyethene



Joined: 11 Aug 2004
Posts: 5248
Location: UK

PostPosted: Wed Aug 22, 2007 6:22 pm    Post subject: Reply with quote

I like the updates, Invoke() and ActiveXObject() will make things a lot easier. Could you also add garbage collection during uninitialization so we don't have to manually release each object.
_________________
GitHubScriptsIronAHK Contact by email not private message.
Back to top
View user's profile Send private message Send e-mail Visit poster's website
Display posts from previous:   
This topic is locked: you cannot edit posts or make replies.    AutoHotkey Community Forum Index -> Scripts & Functions All times are GMT
Goto page Previous  1, 2, 3 ... 8, 9, 10, 11  Next
Page 9 of 11

 
Jump to:  
You can post new topics in this forum
You can reply to topics in this forum


Powered by phpBB © 2001, 2005 phpBB Group