связка Python + C/C++

Вопросы написания собственного программного кода (на любых языках)

Модератор: Olej

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: связка Python + C/C++

Непрочитанное сообщение Olej » 19 авг 2013, 18:19

Olej писал(а): 5-м вариантом есть использование модуля ctypes из стандартной библиотеки модулей Python (/usr/lib/python2.7).
Этот способ получается:
а). самым простым по реализации (написанию кода, технике сборки, не требует никаких дополнительных инструментов и т.д.)
б). самым опасным с точки зрения возможных ошибок: на стыке Python-C отсутствует не только какой-либо контроль правильности соответствия типов ожидаемых параметров, но даже просто их количества!

Вот пример нескольких вызовов, показывающих простоту реализации:

- файл C-реализации модуля call.c - 3 разных функции, с разным числом и типом параметров и разным возвращаемым значением:

Код: Выделить всё

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <locale.h>
#include <wchar.h>

// c_double fun1( c_short )
double fun1( short i ) {
   printf( "получен параметр = %d\n", i );
   return (double)i;
}

// c_void_p fun2( c_char_p )
const char* fun2( const char* s ) {
   printf( "локализация операционной системы: %s\n",
           setlocale( LC_ALL, "" ) );   // по умолчанию, из установок системы
   int nsym = 0;
   const char *p = s;
   while( 1 ) {
      int n = mblen( p, MB_CUR_MAX );
      if( 0 == n ) break;
      nsym++;
      p += n;
   };
   printf( "получен параметр [ mbchar* ] : \"%s\"; длина: в байтах = %d, в символах = %d\n",
           s, strlen( s ), nsym );
   static const char* ret = "возвращаемая строка";
   return ret;
}

// c_void_p fun3( c_float, c_long, c_char_p )
void* fun3( float f, long l, char* s ) {
   printf( "вызов функции 3-х переменных: \"float\"=%f, \"long\"=%ld, \"char*\"=\"%s\"\n",
           f, l, s );
   return (void*)s;
}


- сборка:

Код: Выделить всё

bash-4.2$ gcc -shared -o call.so -fPIC call.c
- вызывающий файл test.py :

Код: Выделить всё

#!/usr/bin/python
# -*- coding: utf-8 -*-

import ctypes

lib = ctypes.CDLL( './call.so' )

print '-----------------------------------------------------'

# === double fun1( short ) ===
# pfun = ctypes.CDLL( './call.so' ).fun1
pfun = lib.fun1
pfun.restype = ctypes.c_double
pfun.argtypes = ( ctypes.c_short, )
x = pfun( 3 )
print 'возвращено значение %f' % x
print '-----------------------------------------------------'

# === const char* fun2( const char* ) ===
#pfun = ctypes.CDLL( './call.so' ).fun2
pfun = lib.fun2
pfun.restype = ctypes.c_char_p
pfun.argtypes = ( ctypes.c_char_p, )
x = pfun( "строка вызова" )
print 'возвращено значение : "%s"' % x
print '-----------------------------------------------------'

# === void* fun3( float, long, char* ) ===
pfun = lib.fun3
pfun.restype = ctypes.c_void_p
pfun.argtypes = ( ctypes.c_float, ctypes.c_long, ctypes.c_char_p )
s = "строка"
x = pfun( 3.1415, -12345, s )
print 'возвращено значение\t= %x' % x
print 'id( строка-параметр )\t= %x' % id( s )
print '-----------------------------------------------------'
- и его выполнение:

Код: Выделить всё

bash-4.2$ python test.py
-----------------------------------------------------
получен параметр = 3
возвращено значение 3.000000
-----------------------------------------------------
локализация операционной системы: ru_RU.UTF-8
получен параметр [ mbchar* ] : "строка вызова"; длина: в байтах = 25, в символах = 13
возвращено значение : "возвращаемая строка"
-----------------------------------------------------
вызов функции 3-х переменных: "float"=3,141500, "long"=-12345, "char*"="строка"
возвращено значение	= b76815ac
id( строка-параметр )	= b7681598
-----------------------------------------------------
Этого примера, думаю, вполне достаточно для написания интерфейса к любого вида C-функциям.
И он же показывает в чём опасность: можно вполне благополучно в C-параметр char* передавать значение floaf, а возвращённый из C-кода указатель void* толковать в Python коде как long... :-o
Вложения
call.tgz
(1.35 КБ) 395 скачиваний

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: связка Python + C/C++

Непрочитанное сообщение Olej » 12 июн 2015, 16:46

Всё, что здесь обсуждалось, + ещё кое что сверх того (что появилось в последнее время) - упорядочено и описано единым связным текстом, и лежит вот здесь: "Взаимосвязь с C/C++".

fedori
Сообщения: 1
Зарегистрирован: 18 июн 2015, 17:49
Контактная информация:

Re: связка Python + C/C++

Непрочитанное сообщение fedori » 19 июн 2015, 13:00

Спасибо за разъяснение. Стоит отметить, что бассейн жемчужина митино http://moskva-severozapad.ru/basseyn-zhemchuzhina-mitino посещают любители плавания. Примечательно, что история тропарево http://zapad-moskva.ru/istoriya-troparevo-nikulino насчитывает несколько столетий.

Ответить

Вернуться в «Программирование»

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и 5 гостей