Creating a pointer to SAFEARRAY(BSTR) for COM object communication

Hi!

I have a hardware driver in DLL format that I would like to invoke from
a Ruby script using the win32ole gem. One of the inputs is defined as a
“SAFEARRAY(BSTR)*” is it possible to create such a pointer in Ruby?

A BSTR type is defined on MSDN. Four byte header with length, then data
and then two null characters as a terminator.

===== WORKING =====
When I call another method defined like this:

HRESULT ICdfGetHandlerByName::GetHandlerByName([in] BSTR HandlerName,
[out, retval] IUnknown ** ppUnk)

I use this Ruby call:
light_i = my_handler_interface.GetHandlerByName(“CdfLight”)

Ruby solves this, I do not assemble the BSTR by hand, not introducing
the header, terminator or anything, not doing anything to get the output
from the double pointer to the result variable. Ot works!

===== NOT WORKING =====
This method however, I just cannot solve how to call:

HRESULT ICdfHandleManager::ListHandleTypes([in, out] long * Count,
[in, out, size_is(Count)] SAFEARRAY(BSTR) HandleTypes )

Anyone have any idéa how to create a pointer ro a SAFEARRAY(BSTR)?

I constantly get “Type mismatch.” and I have tried dussens of different
syntax.

straight_ruby_ldh_api.rb:30:in `method_missing’:
ListHandleTypes(WIN32OLERuntimeError)
OLE error code:0 in

HRESULT error code:0x80020005
Type mismatch.
from straight_ruby_ldh_api.rb:30

(I also tried to assemble the BSTR myself although the calls with
straigh usage of BSTR don’t require me to take any action.

length = 512
data = “x”*(length+4+2)
#Header
length_hs = length.to_s(16)
if (4 < length_hs.length)
raise “To Large Data”
end
for i in (0…3) do
data[i+4-length_hs.length] = length_hs[(i)…(i)].to_i
end

In Python it is very smooth to use this DLL, works of the shelf. I
really need to solve this in order for us to keep Ruby! :-/

Hello,

On Fri, Oct 26, 2012 at 05:46:11PM +0900, Andreas L. wrote:

I have a hardware driver in DLL format that I would like to invoke from
a Ruby script using the win32ole gem. One of the inputs is defined as a
“SAFEARRAY(BSTR)*” is it possible to create such a pointer in Ruby?

(snip)

===== NOT WORKING =====
This method however, I just cannot solve how to call:

HRESULT ICdfHandleManager::ListHandleTypes([in, out] long * Count,
[in, out, size_is(Count)] SAFEARRAY(BSTR) HandleTypes )

How about Array of string?
For example:
[“aaa”, “bbb”, “ccc”]

Or, you could get the hint of inputs by running following script.

m = iCdfHandleManager.method_help(‘listHandleTypes’)
m.params.each do |param|
puts param.ole_type_detail.join(’,’) + ’ ’ + param.name
end

Best Regards,
Masaki S.

Hi!

Unfortunately no success.

The method “method_help” was unfortunately not implemented. I did
however manage to extract some information via Pythons COM-handler. It
said:

def ICdfGetHandlerByName(self, SessionHandles=defaultNamedNotOptArg):
return self.ApplyTypes(1610809349, 1, (24, 0), ((8, 1), (16387, 3),
(24579, 3)), ICdfGetHandlerByName, None,SessionType, Count,
SessionHandles)

The documentation says this:

HRESULT ICdfGetHandlerByName::GetHandlerByName([in] BSTR HandlerName,
[out, retval] IUnknown ** ppUnk)

I tried the array of strings, array of array with strings and all
combinations that I could think of. I guess Ruby is not intended for
communication with peripherals, sw or hw. :frowning:

Thanks anyway and if anyone has any idéas, I am all ears!