ctypes in python size with the `sys.getsizeof(Var)` method vs `ctypes.sizeof(Var)`
Asked Answered
L

3

6

I have a question about variable size in python, I'm using the the Ctypes because i want a 1 byte number, but when I tried to check it's size in python (via sys.getsize) it said it was 80 byte but when i checked with the ctypes (via ctypes.sizeof) it said it was 1 byte only, can someone tell me what is the difference and why is there 2 different sizes? is it because python is using an object or wrapper? and when its sent to c it views the real size?

import sys
import ctypes

print("size in ctypes is : ",ctypes.sizeof(ctypes.c_byte(1)))
print("size in sys is : ",sys.getsizeof(ctypes.c_byte(1)))

results in

size in ctypes is :  1
size in sys is :  80
Level answered 30/11, 2014 at 13:18 Comment(0)
D
4

If you want to know the details, you should take a look at objects.h (especially the comments at the top of the file). Your ctypes.c_byte(1) is a Python object:

>>> import sys
>>> import ctypes
>>> isinstance(ctypes.c_byte(1), object)
True

As noted by @Daniel, sys.getsizeof gets the size of that Python object. That Python object is larger than the corresponding object in C. Note the following from the object.h comments:

Objects are structures allocated on the heap. . . .
The actual memory allocated for an object
contains other data that can only be accessed after casting the pointer
to a pointer to a longer structure type.  This longer type must start
with the reference count and type fields; the macro PyObject_HEAD should be
used for this.

In other words, a macro PyObject_HEAD is attached to the start of every object. This increases the size of the Python object.

ctypes.sizeof, on the other hand, returns the actual size of the C data type that is within the Python object (using C's sizeof operator).

EDIT

In light of your goal that you mention in your comment to Daniel's post, it is possible to send one byte over a server in Python 3.x. Below is an example of how you would send a byte using Python's socket module to prove this point.

Here is the server, which you will run in one Python interpreter:

# Server
import socket

HOST = ''                      # All available interfaces
PORT = 50007                   # Same port as client
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((HOST, PORT))
s.listen(1)
conn, addr = s.accept()
print('Connected by', addr)
while True:
    data = conn.recv(1)        # receive data with bufsize 1; a larger bufsize will break this code
    if not data: break
    conn.sendall(data)
conn.close()

Here is the client, which you will run in another python interpreter:

# Client
import socket

HOST = '127.0.0.1'             # The remote host, but here using localhost
PORT = 50007                   # The port used by both the client and server
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((HOST, PORT))
s.sendall(b'1')                # a bytes object
data = s.recv(1)               # Receive data from the socket with bufsize of 1
s.close()
print('Received', repr(data))  # confirm receipt
Dissonant answered 30/11, 2014 at 14:29 Comment(4)
yeah i guessed that this have happened as i mentioned an object wrapper, so only if it's passed to an actually C code it would count as the ctypes size?Level
@Level Yes, to a certain extent. I see your comment under Daniel's post, and you can attain your goal through Python 3.x. I'll update my post to show you how.Dissonant
Thanks very much, i actually tried this before but it didn't work, must've had something wrong with my code since yours work perfectly :) thanks!Level
@Level Glad to help, and I'm glad you were thinking along the same lines. Cheers.Dissonant
A
3

The ctypes module is used for creating and manipulating C data types in Python. That is why ctypes.sizeof(ctypes.c_byte(1)) returns 1.

>>> import sys
>>> help(sys.getsizeof) Help on built-in function getsizeof in module sys:

getsizeof(...)
    getsizeof(object, default) -> int

    Return the size of object in bytes.

while

>>> import ctypes
>>> help(ctypes.sizeof)
Help on built-in function sizeof in module _ctypes:

sizeof(...)
    sizeof(C type) -> integer
    sizeof(C instance) -> integer
    Return the size in bytes of a C instance

>>>
Addlepated answered 30/11, 2014 at 13:31 Comment(0)
I
2

sys.getsizeof returns the size of a python object, this has nothing to do with the size of a C data type. And it is nothing you have to concern about.

Ionization answered 30/11, 2014 at 13:24 Comment(2)
i have an assignment and i'm supposed to send only 2 bytes via a UDP packet and it's kinda frustrating since i can't find a way to store just a couple of bytes in a variable, prolly shouldn't have chosen python for this type of assignment? but it's not possible that python can't achieve this taskLevel
How do you send your bytes? Just use a bytestring. ctypes is only for communicating with foreign libraries in other languages.Ionization

© 2022 - 2024 — McMap. All rights reserved.