Использование функции C в Python

Я пробовал все решения, упомянутые в Интернете, пока ничего не работало для меня.

У меня есть код на Python, чтобы ускорить его, я хочу, чтобы мой код выполнял тяжелые вычисления в функции C. Я уже написал эту функцию C.

Затем, чтобы поделиться библиотекой, я сделал это в терминале:

gcc -shared -Wl,-install_name,testlib.so -o testlib.so -fPIC myModule.c

который не возвращает ошибку. Проблема; появляется, когда я пытаюсь запустить функцию C в python. Пусть рассмотрим следующую простую функцию в C:

int multiplier(int a, int b)
{

int lol = 0;

lol = a*b;

return lol;
}

Я запускаю python3 (3.5.2), а затем:

import ctypes
zelib = ctypes.CDLL("/Users/longeard/Desktop/Codes/DraII/testlib.so",ctypes.RTLD_GLOBAL)

Библиотека должна быть готова к использованию в python:

res = zelib.multiplier(2,3)

При этом он работает, и python возвращает

6

Проблема в том, что функция, которую я хочу использовать (функция множителя, которую я использую только для примера), должна принимать float как входные данные и возвращать float. Но если теперь я рассмотрю ту же функцию множителя, что и раньше, но с float:

float multiplier(float a, float b)
{

float lol = 0.0;

lol = a*b;

return lol;
}

Я перекомпиляю с помощью gcc, я reimport ctypes и повторно делаю ctypes.CDLL, и я делаю в python3:

zelib.multiplier(ctypes.c_float(2),ctypes.c_float(3))

(types.c_float здесь, чтобы преобразовать 2 в python в float в C), python вернет:

2

Это странно, потому что, если я добавлю printf в функцию для печати lol, python напечатает:

  6.0

но все же возвращают 2 или 18 иногда. Хотя я печатаю и возвращаю ту же переменную "lol".

Я пробовал много чего, и ничто из этого не сработало. У кого-нибудь есть идея, пожалуйста? Спасибо.

Ответ 1

В то время как ответ @falsetru - лучший способ сделать это, альтернатива - просто написать свою функцию C, чтобы использовать удвоения.

Поплавки автоматически повышаются до удвоения при вызове функции без списка параметров.

Ответ 2

Вам нужно указать restype, argtypes функции:

zelib = ctypes.CDLL('...')
zelib.multiplier.restype = ctypes.c_float   # return type
zelib.multiplier.argtypes = [ctypes.c_float, ctypes.c_float]  # argument types

Согласно Указание необходимых типов аргументов (прототипов функций):

Можно указать необходимые типы аргументов функций, экспортируемых из DLL, установив атрибут argtypes.

и Типы возвращаемых данных в документации ctypes:

По умолчанию предполагается, что функции возвращают тип C int. Другие типы возвращаемых данных можно задать, установив атрибут restype объекта функции.


# without specifying types
>>> import ctypes
>>> zelib = ctypes.CDLL('testlib.so')
>>> zelib.multiplier(2, 3)
0

# specifying types
>>> zelib.multiplier.restype = ctypes.c_float
>>> zelib.multiplier.argtypes = [ctypes.c_float, ctypes.c_float]
>>> zelib.multiplier(2, 3)
6.0