Как передать массив в общую библиотеку (.dll), написанную на языке c, с использованием python? - PullRequest
4 голосов
/ 26 марта 2012

код функции файла test.dll:

double __cdecl add(int len,double array[]){}

(и я проверил это в vc)

код питона:

import ctypes
from ctypes import *

N=...
arr=(c_double*N)()
...
...
dll=CDLL("test.dll")
sum=dll.add(c_int(N),byref(arr))

print sum

но код Python не работает, и «сумма» всегда равна N (например, когда N = 10, выдается «сумма = 10») что с ним не так?

Ответы [ 2 ]

9 голосов
/ 26 марта 2012

Передача массива в ctypes отражает передачу массива в C, т.е. вам не нужно передавать ссылку на него, так как массив уже является ссылкой на его первый элемент.

from ctypes import *

N = ...
arr=(c_double*N)()
dll=CDLL("test.dll")
sum=dll.add(c_int(N),arr)

print sum

Примерэто можно увидеть в документации по ctypes в разделе обратных вызовов при обсуждении взаимодействия с qsort.

Редактировать: Согласно комментарию Дэвида Хеффернана, вам также потребуется dll.add.restype = c_double, иначе ctypes приметвозвращаемый тип c_int.

0 голосов
/ 13 мая 2016

Проблема здесь в том, что функция определена как

double __cdecl add(int len, double array[]) { }

Однако, если вы не укажете тип возвращаемого значения для нее, ctypes по умолчанию будет int.Это аналогично объявлению функции в C как

int __cdecl add(int len, double array[]);

Поскольку объявление и определение не совпадают, ваш код имеет неопределенное поведение , то есть:

- Функция определяется с типом, который не совместим с типом (выражения), на который указывает выражение, обозначающее вызываемую функцию (6.5.2.2).


Inв этом конкретном случае вы работаете в архитектуре, где целочисленные значения и значения с плавающей запятой возвращаются в регистрах;однако возвращаемые значения int и double хранятся в различных регистрах.Теперь регистр, который содержит возвращаемое значение типа int в этом ABI, содержит N в качестве остатка.Правильное возвращаемое значение содержалось в регистре с плавающей запятой, однако оно никогда не использовалось, поскольку ctypes ожидал получить int.

Таким образом, правильное исправление - это

dll.add.restype = c_double
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...