将io.\U BufferedReader传递给c函数

将io.\U BufferedReader传递给c函数,c,cpython,python-3.2,C,Cpython,Python 3.2,这个问题是我的问题的后续,在我的问题中,我尝试为Python3编译PythonYenc。在被告知没有快速解决方案后,我决定接受挑战并完全重写它 我唯一搞不懂的是如何在io对象中使用PyArg_ParseTupleAndKeywords。以下是相关代码: PyObject *in_file, *out_file; static char *kwlist[] = { "infile", "outfile", NULL }; if(!PyArg_ParseTupleAndKeywords(args,

这个问题是我的问题的后续,在我的问题中,我尝试为Python3编译PythonYenc。在被告知没有快速解决方案后,我决定接受挑战并完全重写它

我唯一搞不懂的是如何在io对象中使用
PyArg_ParseTupleAndKeywords
。以下是相关代码:

PyObject *in_file, *out_file;
static char *kwlist[] = { "infile", "outfile", NULL };

if(!PyArg_ParseTupleAndKeywords(args, kwds, "O!O!|l", kwlist,\
                     &PyBytes_Type, &in_file,\
                     &PyBytes_Type, &out_file,\
                     &bytes)) return NULL;
这显然会产生

Traceback (most recent call last):
  File "test.py", line 21, in <module>
    print(_yenc.decode_file(b), outfile=o)
TypeError: argument 1 must be bytes, not _io.BufferedReader
回溯(最近一次呼叫最后一次):
文件“test.py”,第21行,在
打印(解码文件(b),输出文件=o)
TypeError:参数1必须是字节,而不是_io.BufferedReader
如何将io.BufferedReader-对象传递给函数

谢谢, Martijn

我已经下载了yenc(https://bitbucket.org/dual75/yenc)并尝试了以下测试程序,但未成功

#include <stdio.h>
#include "_yenc.h"

int main()
{
    PyObject *in_file, *out_file;
    PyObject *args;
    PyObject *kwds;
    int bytes;
    static char *kwlist[] = { "infile", "outfile", NULL };

    if(!PyArg_ParseTupleAndKeywords(args, kwds, "O!O!|l", kwlist,\
                 &PyBytes_Type, &in_file,\
                 &PyBytes_Type, &out_file,\
                 &bytes)) {
        printf("Yay!\n");
    } else {
        printf("Bad luck :( \n");
    }

    return 0;
}
遇到了以下问题:

/tmp/ccRasW2G.o: In function `main':
/home/sangeeth/work/github/yenc/yenc/src/test.c:14: undefined reference to `PyString_Type'
/home/sangeeth/work/github/yenc/yenc/src/test.c:14: undefined reference to `PyString_Type'
/home/sangeeth/work/github/yenc/yenc/src/test.c:14: undefined reference to `PyArg_ParseTupleAndKeywords'
collect2: ld returned 1 exit status
那么,你能分享一下复制这个问题的步骤吗

奥托,我明白了

PyArg_ParseTupleAndKeywords (in src/_yenc.c) 
两者兼而有之

&PyFile_Type 

并且编译良好(python setup.py build)。那么你看到的问题是什么呢?

我已经下载了yenc(https://bitbucket.org/dual75/yenc)并尝试了以下测试程序,但未成功

#include <stdio.h>
#include "_yenc.h"

int main()
{
    PyObject *in_file, *out_file;
    PyObject *args;
    PyObject *kwds;
    int bytes;
    static char *kwlist[] = { "infile", "outfile", NULL };

    if(!PyArg_ParseTupleAndKeywords(args, kwds, "O!O!|l", kwlist,\
                 &PyBytes_Type, &in_file,\
                 &PyBytes_Type, &out_file,\
                 &bytes)) {
        printf("Yay!\n");
    } else {
        printf("Bad luck :( \n");
    }

    return 0;
}
遇到了以下问题:

/tmp/ccRasW2G.o: In function `main':
/home/sangeeth/work/github/yenc/yenc/src/test.c:14: undefined reference to `PyString_Type'
/home/sangeeth/work/github/yenc/yenc/src/test.c:14: undefined reference to `PyString_Type'
/home/sangeeth/work/github/yenc/yenc/src/test.c:14: undefined reference to `PyArg_ParseTupleAndKeywords'
collect2: ld returned 1 exit status
那么,你能分享一下复制这个问题的步骤吗

奥托,我明白了

PyArg_ParseTupleAndKeywords (in src/_yenc.c) 
两者兼而有之

&PyFile_Type 


并且编译良好(python setup.py build)。那么你看到的问题是什么呢?

Mzialla,你不应该在PyArg_ParseTupleAndKeywords中使用“O!”。这样做意味着您不能传递指定类型以外的任何对象。我相信在Python3.2扩展中与文件接口的典型方法不是假定任何特定类型,而是根据“协议”编程

所以你应该做一些类似的事情:

if(!PyArg_ParseTupleAndKeywords(args, kwds, "OO|l", kwlist,\
             &in_file, &out_file, &bytes))
    ...
在这之后,您有两个选项:要么使用流对象的Python方法与流对象交互,要么获取流的文件描述符(PyObject_AsFileDescriptor)并使用操作系统级别/函数(或等效工具)对其进行操作

对于Python方法,您应该获得“read”方法,并调用该方法而不是fread。大致如下(未经测试):

PyObject*read=PyObject_GetAttrString(在_文件中,“read”);
如果(!read)处理错误;
while(编码

然后,您需要在写端执行类似的操作。

Mzialla,您不应该在PyArg_ParseTupleAndKeywords中使用“O!”。这样做意味着您不能传递指定类型以外的任何对象。我相信在Python3.2扩展中与文件接口的典型方法不是假定任何特定类型,而是根据“协议”编程

所以你应该做一些类似的事情:

if(!PyArg_ParseTupleAndKeywords(args, kwds, "OO|l", kwlist,\
             &in_file, &out_file, &bytes))
    ...
在这之后,您有两个选项:要么使用流对象的Python方法与流对象交互,要么获取流的文件描述符(PyObject_AsFileDescriptor)并使用操作系统级别/函数(或等效工具)对其进行操作

对于Python方法,您应该获得“read”方法,并调用该方法而不是fread。大致如下(未经测试):

PyObject*read=PyObject_GetAttrString(在_文件中,“read”);
如果(!read)处理错误;
while(编码
然后,您需要对写端执行类似的操作。

这可以:

PyObject *decode_file(PyObject *pPySelf, 
              PyObject* pPyArgs, 
              PyObject* pPyKeywords) {
  uLong     totDecodedBytes = 0;
  uInt      decodedBytes;
  uLong     bytesToRead;
  uLong     bytesToDecode = 0;
  Bool      escape = 0;
  Crc32     crc;
  PyObject *pPyInFile = NULL;
  PyObject *pPyOutFile = NULL;
  if (!PyArg_ParseTupleAndKeywords(pPyArgs,
                   pPyKeywords,
                   "OO|l",
                   argnames,
                   &pPyInFile,
                   &pPyOutFile,
                   &bytesToDecode)) {
    return NULL;
  }
  crc_init(&crc, 0xffffffffl);
  while (totDecodedBytes < bytesToDecode) {
    char      *readBuffer;
    Byte       writeBuffer[LONGBUFF];
    Py_ssize_t readBytes;
    PyObject  *pPyReadBuffer;
    bytesToRead = bytesToDecode - totDecodedBytes;
    if (bytesToRead > BLOCK) {
      bytesToRead = BLOCK;
    } else if (bytesToRead == 0) {
      break;
    }
    pPyReadBuffer = PyObject_CallMethod(pPyInFile, "read", "l", bytesToRead);
    if (NULL == pPyReadBuffer) {
      break;
    }
    PyBytes_AsStringAndSize(pPyReadBuffer, &readBuffer, &readBytes);
    decodedBytes = decode_buffer((Byte*)readBuffer,
                 writeBuffer,
                 readBytes,
                 &crc,
                 &escape);
    PyObject_CallMethod(pPyOutFile, "write", "y#", writeBuffer, decodedBytes);
    totDecodedBytes += decodedBytes;
  }
  return Py_BuildValue("(l,L)", totDecodedBytes, (long long)crc.crc);
}
PyObject*解码文件(PyObject*pPySelf,
PyObject*pPyArgs,
PyObject*pPyKeywords){
uLong totdebytes=0;
uInt解码字节;
乌龙比德斯特雷德;
uLong bytesToDecode=0;
布尔逃逸=0;
Crc32-crc;
PyObject*pPyInFile=NULL;
PyObject*pPyOutFile=NULL;
如果(!PyArg_ParseTupleAndKeywords(pPyArgs,
pPyKeywords,
“OO | l”,
argnames,
&pPyInFile,
&pPyOutFile,
&ByTestCode){
返回NULL;
}
crc_init(&crc,0xFFFFFFFFFFL);
while(totDecodedBytesBLOCK){
bytesToRead=块;
}else if(bytesToRead==0){
打破
}
pPyReadBuffer=PyObject_CallMethod(pPyInFile,“read”,“l”,bytesToRead);
if(NULL==pPyReadBuffer){
打破
}
PyBytes_AsStringAndSize(pPyReadBuffer、&readBuffer和&readBytes);
decodedBytes=解码缓冲区((字节*)读缓冲区,
writeBuffer,
readBytes,
&华润,
&逃逸);
PyObject_调用方法(pPyOutFile,“write”,“y#”,writeBuffer,decodedBytes);
totDecodedBytes+=已解码字节;
}
返回Py_BuildValue(“(l,l)”,totDecodedBytes,(long-long)crc.crc);
}
这项工作:

PyObject *decode_file(PyObject *pPySelf, 
              PyObject* pPyArgs, 
              PyObject* pPyKeywords) {
  uLong     totDecodedBytes = 0;
  uInt      decodedBytes;
  uLong     bytesToRead;
  uLong     bytesToDecode = 0;
  Bool      escape = 0;
  Crc32     crc;
  PyObject *pPyInFile = NULL;
  PyObject *pPyOutFile = NULL;
  if (!PyArg_ParseTupleAndKeywords(pPyArgs,
                   pPyKeywords,
                   "OO|l",
                   argnames,
                   &pPyInFile,
                   &pPyOutFile,
                   &bytesToDecode)) {
    return NULL;
  }
  crc_init(&crc, 0xffffffffl);
  while (totDecodedBytes < bytesToDecode) {
    char      *readBuffer;
    Byte       writeBuffer[LONGBUFF];
    Py_ssize_t readBytes;
    PyObject  *pPyReadBuffer;
    bytesToRead = bytesToDecode - totDecodedBytes;
    if (bytesToRead > BLOCK) {
      bytesToRead = BLOCK;
    } else if (bytesToRead == 0) {
      break;
    }
    pPyReadBuffer = PyObject_CallMethod(pPyInFile, "read", "l", bytesToRead);
    if (NULL == pPyReadBuffer) {
      break;
    }
    PyBytes_AsStringAndSize(pPyReadBuffer, &readBuffer, &readBytes);
    decodedBytes = decode_buffer((Byte*)readBuffer,
                 writeBuffer,
                 readBytes,
                 &crc,
                 &escape);
    PyObject_CallMethod(pPyOutFile, "write", "y#", writeBuffer, decodedBytes);
    totDecodedBytes += decodedBytes;
  }
  return Py_BuildValue("(l,L)", totDecodedBytes, (long long)crc.crc);
}
PyObject*解码文件(PyObject*pPySelf,
PyObject*pPyArgs,
PyObject*pPyKeywords){
uLong totdebytes=0;
uInt解码字节;
乌龙比德斯特雷德;
uLong bytesToDecode=0;
布尔逃逸=0;
Crc32-crc;
PyObject*pPyInFile=NULL;
PyObject*pPyOutFile=NULL;
如果(!PyArg_ParseTupleAndKeywords(pPyArgs,
pPyKeywords,
“OO | l”,
argnames,
&pPyInFile,
&pPyOutFile,
&ByTestCode){
返回NULL;
}
crc_init(&crc,0xFFFFFFFFFFL);
while(totDecodedBytes