Charles Duffy
Charles Duffy

Reputation: 295472

Using COM interfaces with initialized OUT parameters via Python comtypes library

I'm using a 3rd-party C++ library (exporting a typelib via COM) from Python via the comtypes module.

One of the available calls defines an OUT parameter, like so:

COMMETHOD([helpstring(u'method GetPacket')], HRESULT, 'GetPacket',
          ( ['in'], comtypes.gen._00020430_0000_0000_C000_000000000046_0_2_0.GUID, 'guid' ),
          ( ['in'], c_int, 'lSize' ),
          ( ['out'], POINTER(c_ubyte), 'pData' )),

The C++ example code provided by the library's author initializes pData to be a byte array of length lSize before invoking GetPacket(), like so:

pPacket = new BYTE[lSize];
HRESULT hr = pData->GetPacket(guid, lSize, pPacket);

However, the comtypes library for Python doesn't provide a way to pass an initial value for pData -- and, on calling the library with no initial value, the interpreter promptly segfaults.

Is it possible to interoperate with this library from Python -- ideally, from comtypes?

Upvotes: 3

Views: 886

Answers (1)

acelent
acelent

Reputation: 8135

It is possible with some low-level changes to the generated GetPacket.

Source: [comtypes-users] Right way to call a method with a pointer to array?

# change GetPacket so the second argument is in, not out
packet = (c_ubyte * size)()
data.GetPacket(guid, size, packet)

However, note that typelibs don't contain information about size_is, length_is and a few other things. This means that the generic typelib marshaller proxies and stubs, used across apartment and process boundaries, will not look into lSize to determine how many elements to serialize from pData, it'll always (try to) serialize a single pointed item.

In other words, that kind of code, whether C++ or Python, will only work in the same apartment.

Upvotes: 1

Related Questions