AutoHotkey Community

It is currently May 25th, 2012, 10:12 am

All times are UTC [ DST ]




Post new topic This topic is locked, you cannot edit posts or make further replies.  [ 156 posts ]  Go to page Previous  1 ... 6, 7, 8, 9, 10, 11  Next
Author Message
 Post subject:
PostPosted: July 4th, 2007, 3:55 am 
Offline

Joined: May 20th, 2007, 7:48 pm
Posts: 48
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.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: July 7th, 2007, 4:12 pm 
Offline

Joined: May 20th, 2007, 7:48 pm
Posts: 48
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.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: July 7th, 2007, 6:26 pm 
Offline

Joined: February 12th, 2007, 7:54 am
Posts: 2462
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!


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: July 7th, 2007, 7:39 pm 
Offline

Joined: May 20th, 2007, 7:48 pm
Posts: 48
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.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: July 8th, 2007, 5:02 am 
Offline

Joined: February 12th, 2007, 7:54 am
Posts: 2462
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)


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: July 8th, 2007, 6:28 am 
Offline

Joined: May 20th, 2007, 7:48 pm
Posts: 48
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.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: July 14th, 2007, 5:00 pm 
Offline

Joined: June 27th, 2007, 9:07 pm
Posts: 101
Location: California
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


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: July 14th, 2007, 11:13 pm 
Offline

Joined: February 12th, 2007, 7:54 am
Posts: 2462
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.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: July 26th, 2007, 6:00 am 
Offline

Joined: February 12th, 2007, 7:54 am
Posts: 2462
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.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: July 26th, 2007, 7:37 am 
Offline

Joined: May 20th, 2007, 7:48 pm
Posts: 48
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
}


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: July 26th, 2007, 9:49 am 
Offline

Joined: February 12th, 2007, 7:54 am
Posts: 2462
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?


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: July 26th, 2007, 1:57 pm 
Offline

Joined: June 27th, 2007, 9:07 pm
Posts: 101
Location: California
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


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: July 26th, 2007, 3:05 pm 
Offline

Joined: May 20th, 2007, 7:48 pm
Posts: 48
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.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: July 26th, 2007, 11:51 pm 
Offline

Joined: February 12th, 2007, 7:54 am
Posts: 2462
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.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: August 22nd, 2007, 7:22 pm 
Offline
User avatar

Joined: August 11th, 2004, 1:47 am
Posts: 5346
Location: UK
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.


Report this post
Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic This topic is locked, you cannot edit posts or make further replies.  [ 156 posts ]  Go to page Previous  1 ... 6, 7, 8, 9, 10, 11  Next

All times are UTC [ DST ]


Who is online

Users browsing this forum: Google Feedfetcher and 11 guests


You can post new topics in this forum
You can reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Powered by phpBB® Forum Software © phpBB Group