Я пытаюсь выяснить, как вернуть 2 значения из функции C, которую я вызвал в python. Я прочитал материалы в Интернете и использую структуру для вывода двух переменных. Я могу выводить переменные, когда вызываю эту функцию в том же файле C. Однако, когда я пытаюсь вызвать его в python, он по-прежнему возвращает только одно значение.
Это мой код на C:
struct re_val {
double predict_label;
double prob_estimates;
};
struct re_val c_func(const char* dir, double a, double b, double c, double d )
{
double x[] = {a,b,c,d};
printf ("x[0].index: %d \n", 1);
printf ("x[0].value: %f \n", x[0]);
printf ("x[1].index: %d \n", 2);
printf ("x[1].value: %f \n", x[1]);
printf ("x[2].index: %d \n", 3);
printf ("x[2].value: %f \n", x[2]);
printf ("x[3].index: %d \n", 4);
printf ("x[3].value: %f \n", x[3]);
printf ("\nThis is the Directory: %s \n", dir);
struct re_val r;
r.predict_label = 5.0;
r.prob_estimates = 8.0;
return r;
}
Это мой код Python:
calling_function = ctypes.CDLL("/home/ruven/Documents/Sonar/C interface/Interface.so")
calling_function.c_func.argtypes = [ctypes.c_char_p, ctypes.c_double, ctypes.c_double, ctypes.c_double, ctypes.c_double]
calling_function.c_func.restype = ctypes.c_double
q = calling_function.c_func("hello",1.3256, 2.45, 3.1248, 4.215440)
print q
В настоящее время, когда я запускаю свой файл python в терминале, он выводит следующее:
x[0].index: 1
x[0].value: 1.325600
x[1].index: 2
x[1].value: 2.450000
x[2].index: 3
x[2].value: 3.124800
x[3].index: 4
x[3].value: 4.215440
This is the Directory: hello
5.0
Вместо этого я хотел бы вывести это:
x[0].index: 1
x[0].value: 1.325600
x[1].index: 2
x[1].value: 2.450000
x[2].index: 3
x[2].value: 3.124800
x[3].index: 4
x[3].value: 4.215440
This is the Directory: hello
5.0
8.0
Проблема в calling_function.c_func.restype = ctypes.c_double. Вы, по сути, говорите ctypes, что тип результата функции - c_double, тогда как функция из вашей библиотеки c не возвращает double, она возвращает struct re_val.
@hetepeperfan Я подумал об этом, но не смог найти способ изменить call_function.c_func.restype для возврата структуры, поскольку ctypes.c_struct не существует.






Ваш код C в порядке, проблема, с которой вы столкнулись, заключается в том, как вы используете python ctypes. Вы должны сказать, что функция возвращает struct re_val, а не double:
calling_function.c_func.restype = ctypes.c_double
Вышеупомянутое заставляет функцию возвращать одно двойное значение в глазах ctypes. Вы должны сообщить python, что функция возвращает структуру:
import ctypes as ct
# Python representation of the C struct re_val
class ReVal(ct.Structure):
_fields_ = [("predict_label", ct.c_double),("prob_estimates", ct.c_double)]
calling_function = ctypes.CDLL("/home/ruven/Documents/Sonar/C interface/Interface.so")
calling_function.c_func.argtypes = [ctypes.c_char_p, ctypes.c_double, ctypes.c_double, ctypes.c_double, ctypes.c_double]
# and instead of c_double use:
calling_function.c_func.restype = ReVal
Таким образом вы сообщаете ctypes python, что функция возвращает агрегированный объект, который является подклассом ctypes.Structure, который соответствует struct re_val из библиотеки c.
ПРИМЕЧАНИЕ Будьте очень осторожны с argtypes и restype, если вы используете их неправильно, интерпретатор python легко выйдет из строя. Тогда вы получите segfault вместо хорошей трассировки.
Привет, к сожалению, когда я запускаю программу, она выдает следующее сообщение: <__ main __. ReVal object at 0x7fb3bd1e0560>
Да, это верно, но это структура, возвращаемая ctypes, она по-прежнему является агрегатом. Таким образом, возвращаемый объект имеет два поля: «pred_label» и «prob_estimates». Таким образом, вы можете получить к ним доступ через q.predict_label и q.prob_estimates. Обычно вам нужно предпринять некоторые дополнительные шаги для извлечения значений из структуры.
Не знаю, сработает этот код или нет, но. проверьте эту ссылку. это может быть вам полезно. gist.github.com/Overdrivr/cdd58cea15d7e28c50ea