#python #windows #types #comtypes
#python #Windows #типы #comtypes
Вопрос:
Я прочитал много документов, примеров и разделов StackOverflow, но все равно это не работает! Я пишу интерфейс Python для своих COM-объектов C . Я делаю это не в первый раз. В прошлом я успешно использовал comtypes для получения отдельных указателей интерфейса и передавал им свои COM-классы, но на этот раз мне нужно передать указатель на массив указателей интерфейса.
Интерфейс COM, который мне нужно вызвать:
STDMETHOD(ExportGeopackage)([in] IMap* pMap,
[in] imageFormatType imageFormat,
[in] long imageQuality,
[in] long zoomMin,
[in] long zoomMax,
[in] IFeatureLayer** attributeExportLayers,
[in] BSTR title,
[in] BSTR description,
[in] BSTR saveToPath,
[in] ITrackCancel* pTrackCancel);
Ожидается, что аргумент attributeExportLayers будет указателем на массив указателей IFeatureLayer C с нулевым завершением. ExportGeopackage() уже был протестирован с клиентами C . Я пишу первый клиент Python.
В Python:
# append a null pointer to the list of comtypes IFeatureLayer pointers
exportLayers.append(comtypes.cast(0, comtypes.POINTER(esriCarto.IFeatureLayer)))
# create ctypes array and populate
PointerArray = ctypes.c_void_p * len(exportLayers)
pointers = PointerArray()
for i in range(len(exportLayers)):
pointers[i] = exportLayers[i]
# export is comtypes interface pointer acquired earlier
export.ExportGeopackage(map, format, quality, min, max,
ctypes.cast(pointers, ctypes.POINTER(esriCarto.IFeatureLayer)),
title, desc, geopackage_path, 0)
Сравнение дампов Python содержимого переменных exportLayer и pointers показывает, что значения указателей успешно передаются из первого во второй. Тесты этих указателей на Python прошли успешно. Однако, когда я выполняю отладку в ExportGeopackage(), память, на которую указывает attributeExportLayers, не имеет никакого сходства с ожидаемым массивом указателей IFeatureLayer. Это выглядит как одиночный указатель (указывающий не на то место), за которым следует длинная строка нулевых указателей. Думая, что, возможно, переменная указателей Python уже была собрана мусором, я добавил ссылку на указатели после вызова ExportGeopackage(). Это не имело никакого значения.
Я каким-то образом вставляю дополнительный уровень косвенности или недостаточно косвенности? Я озадачен.
TIA за любую помощь (или догадки). Алан
Ответ №1:
Еще раз, отвечая на мой собственный вопрос. Помимо требуемого, вводится дополнительный уровень косвенности. По-видимому, в отличие от приведения в C, ctypes.cast фактически принимает адрес первого аргумента.
Изменить:
PointerArray = ctypes.c_void_p * len(exportLayers)
Для:
PointerArray = comtypes.POINTER(esriCarto.IFeatureLayer) * len(exportLayers)
И исключить использование ctypes.cast в вызове ExportGeopackage():
export.ExportGeopackage(map, format, quality, min, max,
pointers,
title, desc, geopackage_path, 0)