Question

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?

Was it helpful?

Solution

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top