Как вы называете код Python кодом C?

Я хочу расширить большой проект C с некоторыми новыми функциями, но я действительно хочу написать его на Python. В принципе, я хочу вызвать код Python из C-кода. Тем не менее, оболочки Python-> C, такие как SWIG, позволяют OPPOSITE, которые пишут C-модули и вызывают C из Python.

Я рассматриваю подход, включающий IPC или RPC (я не против иметь несколько процессов); то есть, когда мой компонент pure-Python запускается в отдельном процессе (на том же компьютере) и имеет возможность связать мой проект C с записью / чтением из сокета (или Unix-канала). мой компонент python может читать / записывать в сокет для связи. Это разумный подход? Есть что-то лучше? Как какой-то специальный механизм RPC?

Спасибо за ответ до сих пор. Тем не менее, я хотел бы сосредоточиться на подходах на основе IPC, так как хочу, чтобы моя программа Python выполнялась в отдельном процессе как моя программа на C. Я не хочу встраивать интерпретатор Python. Благодаря!

8 Solutions collect form web for “Как вы называете код Python кодом C?”

Я рекомендую подходы, подробно описанные здесь . Он начинается с объяснения того, как выполнять строки кода Python, а затем излагает, как настроить среду Python для взаимодействия с вашей программой на C, вызывать функции Python из вашего C-кода, управлять объектами Python из вашего кода C и т. Д.

EDIT : Если вы действительно хотите пойти по маршруту IPC, то вам захочется использовать структурный модуль или еще лучше, protlib . Большая часть связи между процессом Python и C вращается вокруг передачи структур взад и вперед либо через сокет, либо через общую память .

Я рекомендую создать структуру Command с полями и кодами для представления команд и их аргументов. Я не могу дать более конкретные рекомендации, не зная больше о том, чего вы хотите достичь, но в целом я рекомендую библиотеку protlib , так как это то, что я использую для общения между программами C и Python (отказ от ответственности: я являюсь автором protlib) ,

См. Соответствующую главу в руководстве: http://docs.python.org/extending/

По сути вам придется встроить интерпретатор python в вашу программу.

Рассматривали ли вы просто перенос приложения python в сценарий оболочки и вызов его из приложения C?

Не самое изящное решение, но это очень просто.

Я не использовал IPC-подход для связи Python <-> C, но он должен работать очень хорошо. Я хотел бы, чтобы программа C выполняла стандартный fork-exec и использовала перенаправленные stdin и stdout в дочернем процессе для связи. Хорошее текстовое общение облегчит разработку и тестирование программы Python.

Если бы я решил пойти с IPC, я бы, вероятно, проиграл XML-RPC – кросс-платформу, вы можете легко добавить проект Python на другой узел позже, если хотите, имеет много отличных реализаций (см. Здесь для многих , включая C и Python, и здесь для простого XML-RPC-сервера, который является частью стандартной библиотеки Python – не такой масштабируемый, как другие подходы, но, вероятно, он подходит и для вашего варианта использования).

Возможно, это не идеальный подход IPC для всех случаев (или даже идеальный RPC-один, во что бы то ни стало!), Но удобство, гибкость, надежность и широкий спектр реализаций, на мой взгляд, перевешивают множество мелких дефектов.

видимо, Python должен быть способен скомпилировать win32 dll, он решит проблему

Таким образом, преобразование кода c # в dll win32 сделает его пригодным для использования любым средством разработки

Это кажется довольно приятным http://thrift.apache.org/ , есть даже книга об этом.

Детали:

Программная среда Apache Thrift для масштабируемой разработки межязыковых сервисов объединяет стек программного обеспечения с механизмом генерации кода для создания сервисов, которые работают эффективно и плавно между C ++, Java, Python, PHP, Ruby, Erlang, Perl, Haskell, C #, Какао, JavaScript, Node.js, Smalltalk, OCaml и Delphi и другие языки.

Я использовал «стандартный» подход Embedding Python в другом приложении . Но это сложно / утомительно. Каждая новая функция в Python является болезненной для реализации.

Я видел пример вызова PyPy с C. Он использует CFFI для упрощения интерфейса, но для него требуется PyPy, а не Python. Сначала прочитайте и поймите этот пример, по крайней мере, на высоком уровне.

Я изменил пример C / PyPy для работы с Python. Вот как вызвать Python из C с помощью CFFI.

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

Сложная часть теперь выделена для передачи адреса api на Python. Это нужно выполнить только один раз. После этого легко добавить новые функции в Python.

interface.h

 // These are the three functions that I implemented in Python. // Any additional function would be added here. struct API { double (*add_numbers)(double x, double y); char* (*dump_buffer)(char *buffer, int buffer_size); int (*release_object)(char *obj); }; 

test_cffi.c

 // // Calling Python from C. // Based on Calling PyPy from C: // http://doc.pypy.org/en/latest/embedding.html#more-complete-example // #include <stdio.h> #include <assert.h> #include "Python.h" #include "interface.h" struct API api; /* global var */ int main(int argc, char *argv[]) { int rc; // Start Python interpreter and initialize "api" in interface.py using // old style "Embedding Python in Another Application": // https://docs.python.org/2/extending/embedding.html#embedding-python-in-another-application PyObject *pName, *pModule, *py_results; PyObject *fill_api; #define PYVERIFY(exp) if ((exp) == 0) { fprintf(stderr, "%s[%d]: ", __FILE__, __LINE__); PyErr_Print(); exit(1); } Py_SetProgramName(argv[0]); /* optional but recommended */ Py_Initialize(); PyRun_SimpleString( "import sys;" "sys.path.insert(0, '.')" ); PYVERIFY( pName = PyString_FromString("interface") ) PYVERIFY( pModule = PyImport_Import(pName) ) Py_DECREF(pName); PYVERIFY( fill_api = PyObject_GetAttrString(pModule, "fill_api") ) // "k" = [unsigned long], // see https://docs.python.org/2/c-api/arg.html#c.Py_BuildValue PYVERIFY( py_results = PyObject_CallFunction(fill_api, "k", &api) ) assert(py_results == Py_None); // Call Python function from C using cffi. printf("sum: %f\n", api.add_numbers(12.3, 45.6)); // More complex example. char buffer[20]; char * result = api.dump_buffer(buffer, sizeof buffer); assert(result != 0); printf("buffer: %s\n", result); // Let Python perform garbage collection on result now. rc = api.release_object(result); assert(rc == 0); // Close Python interpreter. Py_Finalize(); return 0; } 

interface.py

 import cffi import sys import traceback ffi = cffi.FFI() ffi.cdef(file('interface.h').read()) # Hold references to objects to prevent garbage collection. noGCDict = {} # Add two numbers. # This function was copied from the PyPy example. @ffi.callback("double (double, double)") def add_numbers(x, y): return x + y # Convert input buffer to repr(buffer). @ffi.callback("char *(char*, int)") def dump_buffer(buffer, buffer_len): try: # First attempt to access data in buffer. # Using the ffi/lib objects: # http://cffi.readthedocs.org/en/latest/using.html#using-the-ffi-lib-objects # One char at time, Looks inefficient. #data = ''.join([buffer[i] for i in xrange(buffer_len)]) # Second attempt. # FFI Interface: # http://cffi.readthedocs.org/en/latest/using.html#ffi-interface # Works but doc says "str() gives inconsistent results". #data = str( ffi.buffer(buffer, buffer_len) ) # Convert C buffer to Python str. # Doc says [:] is recommended instead of str(). data = ffi.buffer(buffer, buffer_len)[:] # The goal is to return repr(data) # but it has to be converted to a C buffer. result = ffi.new('char []', repr(data)) # Save reference to data so it's not freed until released by C program. noGCDict[ffi.addressof(result)] = result return result except: print >>sys.stderr, traceback.format_exc() return ffi.NULL # Release object so that Python can reclaim the memory. @ffi.callback("int (char*)") def release_object(ptr): try: del noGCDict[ptr] return 0 except: print >>sys.stderr, traceback.format_exc() return 1 def fill_api(ptr): global api api = ffi.cast("struct API*", ptr) api.add_numbers = add_numbers api.dump_buffer = dump_buffer api.release_object = release_object 

Обобщение:

 gcc -o test_cffi test_cffi.c -I/home/jmudd/pgsql-native/Python-2.7.10.install/include/python2.7 -L/home/jmudd/pgsql-native/Python-2.7.10.install/lib -lpython2.7 

Выполнение:

 $ test_cffi sum: 57.900000 buffer: 'T\x9e\x04\x08\xa8\x93\xff\xbf]\x86\x04\x08\x00\x00\x00\x00\x00\x00\x00\x00' $ 
  • Вставить bash в python
  • Python - лучший язык программирования в мире.