11
votes

Python CTYPES: objet de fichier python <-> C fichier *

J'utilise CYPES pour envelopper une bibliothèque C (que j'ai le contrôle) avec Python. Je veux envelopper une fonction c avec la déclaration: xxx pré>

maintenant; J'aimerais ouvrir le fichier en python, puis utiliser l'objet Python File-Object (d'une manière ou d'une autre manière ??) Pour avoir accès à l'objet de fichier sous-jacent * et transmettez-le à la fonction C: p>

# Python
fileH = open( file , "r")
value = ctypes_function_fread_int( ????? )
fileH.close()


0 commentaires

6 Réponses :


28
votes

Un objet de fichier Python n'est pas nécessairement avoir un fichier de niveau C sous-jacent * - au moins, pas à moins que vous n'êtes pas prêt à attacher votre code extrêmement spécifique Versions et plates-formes Python.

Ce que je recommanderais à la place consiste à utiliser le fichier fileno pour obtenir un descripteur de fichier, puis utiliser ctypes pour appeler le fdopen Pour créer un fichier * de que . C'est une approche très portable (et vous pouvez également aller dans l'autre sens). Le gros problème est que la mise en mémoire tampon sera séparée pour les deux objets ouverts sur le même descripteur de fichier (l'objet de fichier Python et le fichier C * ), assurez-vous donc de couper lesdits objets aussi souvent que nécessaire (Ou, ouvert à la fois désespéré, si cela est plus pratique et compatible avec votre utilisation prévue).


2 commentaires

Merci beaucoup - J'ai eu ce sentiment que le fichier de niveau C * ne serait pas très robuste. Je ne connaissais pas l'attribut Fileno de l'objet de fichier Python - mais cela semble être un moyen naturel d'y aller.


J'ai eu un problème importer STDIN / STDOUT / STDERR d'un SO, et il n'y avait aucune chance que j'allais construire une structure formelle. Votre suggestion Fdopen () m'a sauvé. Merci.



2
votes

Eh bien;

J'ai essayé la solution basée sur Fileno Fileno , mais était tout à fait mal à l'aise avec l'ouverture du fichier deux fois; Il n'était pas non plus clair pour moi comment éviter la valeur de retour de fdopen () pour fuir.

à la fin j'ai écrit une extension C microscopique: < Pré> xxx

qui utilise pyfile_asfile comme une valeur de pointeur pure sur python qui passe cette fonction de retour à C code> fichier * entrée. Cela fonctionne au moins.

JOAKIM


0 commentaires

-1
votes

J'ai rencontré le même problème.

Jetez un coup d'œil à ce fichier:

http://svn.python.org/ Projets / CTTPES / Trunk / CTTYPESLIB / CTTYPESLIB / PLATE / PYTHONHDR.PY

Vous pouvez utiliser pyfile_asfile de celui-ci.


3 commentaires

Merci - c'était une meilleure solution que la mienne.


Malheureusement, pyfile_asfile n'existe pas dans l'API Python 3 C.


@Mikhailkorobov: j'ai demandé à une question pour résoudre ce problème.



3
votes

Si vous souhaitez utiliser stdout code> / stdin code> / stdin code>, vous pouvez importer ces variables à partir de la bibliothèque C standard C.

class FILE(ctypes.Structure):
    pass

FILE_p = ctypes.POINTER(FILE)

libc = ctypes.cdll.LoadLibrary('libc.so.6')
cstdout = FILE_p.in_dll(libc, 'stdout')


0 commentaires

0
votes

adapté de SVPlayer

import sys

from ctypes import POINTER, Structure, py_object, pythonapi


class File(Structure):
    pass

if sys.version_info[0] > 2:
    convert_file = pythonapi.PyObject_AsFileDescriptor
    convert_file.restype = c_int
else:
    convert_file = pythonapi.PyFile_AsFile
    convert_file.restype = POINTER(File)

convert_file.argtypes = [py_object]

fp = open('path').fp
c_file = convert_file(fp)


3 commentaires

Sauf que ce problème: pour py3k c_file sera int , pour py2k, il sera fichier * .


@MCEPL que vous dérangeez la réponse pour le rendre correct?


Je crois que la bonne réponse est dans ma solution ci-dessus.



0
votes

essayé ceci: xxx

On dirait que cela pourrait fonctionner.


0 commentaires