How to write partial of a buffer which was returned from a C function to a file?

Jach Fong jfong at ms4.hinet.net
Thu Apr 12 20:38:36 EDT 2018


Gregory Ewing at 2018/4/13 上午 07:25 wrote:
>>>> On Thu, Apr 12, 2018 at 2:16 PM,  <jfong at ms4.hinet.net> wrote:
>>>>
>>>>> This C function returns a buffer which I declared it as a
>>>>> ctypes.c_char_p. The buffer has size 0x10000 bytes long and the valid
>>>>> data may vary from a few bytes to the whole size.
> 
> I think we need to see the code you're using to call this
> C function.
> 
> The crucial issue is: are *you* allocating this 0x10000 byte
> buffer and telling the function to read data into it, or
> does the function allocate the memory itself and return a
> pointer to it?

I am working on a DLL's function.

> 
> If the function is allocating the buffer, then I don't
> think there's any way to make this work. The ctypes docs
> say this:
> 
>> Fundamental data types, when returned as foreign function call results 
>> ... are
>> transparently converted to native Python types. In other words, if a 
>> foreign
>> function has a restype of c_char_p, you will always receive a Python 
>> bytes
>> object, not a c_char_p instance.
> 
> The problem is that the only way ctypes can tell how long
> a bytes object to create for a c_char_p is by assuming that
> it points to a nul-terminated string. If it actually points
> to a char array that can legitimately contain zero bytes,
> then you're out of luck.
> 
> To get around this, you may need to declare the return type
> as POINTER(c_char) instead:
> 
>> For a general character pointer that may also point to binary data,
>  > POINTER(c_char) must be used.

I had missed this statement:-(

To make a quick try, I set the function's restype to 
ctypes.POINTER(ctypes.c_ubyte), instead of ctypes.c_char_p. It's 
amazing, the \x00 trap can be avoided in this way. Now I can use "mydata 
= bytes(buf[:n])" to extract n bytes of data and write it to file.

The problem was solved, and thanks for all your help.

--Jach
> 
> I'm not sure where to go from here, though, because the
> ctypes documentation peters out before explaining exactly
> what can be done with a POINTER object.
> 
> Another approach would be to allocate the buffer yourself
> and pass it into the C function, but whether that's possible
> depends on the details of the C API you're using.
> 

---
This email has been checked for viruses by Avast antivirus software.
https://www.avast.com/antivirus



More information about the Python-list mailing list