Я хотел бы иметь возможность использовать функции C / C ++ из Python с использованием модуля Python ctypes.
У меня есть функция int doit()
в .c
/ .cpp
файл. Когда я пытаюсь загрузить общую библиотеку:
Frr=CDLL("/path/FoCpy2/libFrr.so")
Frr.doit(c_int(5))
я считаю, что это работает очень хорошо, когда .c
вариант используется. Когда вызывается C ++, хорошим способом вызова этой функции является (выясняется с помощью nm libFrr.so
с помощью nm -gC libFrr.so
производит просто doit()
):
Frr._Z4doitv(c_int(5))
Я прочитал на Stackexchange, что нет стандартного способа вызова C ++ из python, и есть проблема «нестандартного искажения имени». Является ли «Z4» частью этой проблемы? Я предполагаю, что нестандартное искажение имени появилось бы для более продвинутых функций языка, таких как методы класса, шаблоны, но также и для таких основных функций? Можно ли принудительно использовать простые имена функций C в простых случаях для кода C ++?
Ты можешь использовать extern "C"
сделать так, чтобы функции выглядели как функции C для внешнего мира (то есть отключить искажение имен). И да, вы правы, преобразование имен необходимо в основном для более сложных функций и типов функций, которые есть в C ++, а схема преобразования имен никогда не была стандартизирована (и двоичная совместимость), поэтому она варьируется от компилятора к компилятору. и между версиями (но большинство компиляторов основного потока в настоящее время установили что-то постоянное, но между поставщиками компиляторов все еще различаются). И причина того, что искажение также требуется для простых старых свободных функций, заключается в том, что C ++ поддерживает перегрузку (те же имена функций, но с разными параметрами), и, таким образом, компиляторы будут кодировать спецификацию параметров (например, типы) в искаженные имена. Конечно, если вы используете extern "C"
вы теряете все функции, для которых необходимо преобразование имен, поэтому оно более или менее сводится только к функциям C.
Ты можешь использовать extern "C"
либо для каждой функции, например, так:
extern "C" int doit();
Или для общего заголовка:
extern "C" {
// all the function declarations here ...
};
Однако, особенно для Python, я настоятельно рекомендую вам использовать библиотеку, которая позволяет вам создавать классы и функции Python, которые отражают ваши классы и функции C ++, что делает жизнь намного проще и скрывает весь этот внешний бизнес «C» , Я рекомендую использовать Boost.Python, видеть это Начальная страница, это делает экспорт функций и классов в Python быстрым. Я думаю, что другие также рекомендуют SWIG, но я никогда не использовал это.
Вызов библиотечных функций c ++ всегда беспорядок, даже если вы используете C ++, вы должны использовать тот же компилятор и т. Д., Чтобы убедиться, что он работает.
Единственное общее решение — определить ваши функции c ++ как extern "C"
и убедитесь, что вы соблюдаете соответствующие ограничения — см. Вот для объяснения этого.