Python ctypes return values question
Asked Answered
W

3

12

Why if i have this simple code

void voidFunct() {
      printf("voidFunct called!!!\n");
}

I compile it as a dynamic library with

gcc -c LSB.c -o LSB.o 
gcc -shared -Wl -o libLSB.so.1 LSB.o 

And i call function from a python interpreter, using ctypes

>>> from ctypes import *
>>> dll = CDLL("./libLSB.so.1")
>>> return = dll.voidFunct()
voidFunct called!!!
>>> print return
17

why the value returned from a void method is 17 and not None or similar? Thank you.

Wolver answered 20/5, 2011 at 14:45 Comment(1)
Hmm, I'm pretty sure you can't write return = dll.voidFunct() in Python. return is a reserved word.Douche
D
37

From the docs:

class ctypes.CDLL(name, mode=DEFAULT_MODE, handle=None, use_errno=False, use_last_error=False)

Instances of this class represent loaded shared libraries. Functions in these libraries use the standard C calling convention, and are assumed to return int.

In short, you defined voidFunct() as a functioning returning int, not void, and Python expects it to return an int (which it gets, somehow, anyway - it's just happen to be a random value).

What you should probably do, is to explicitly state a return value type of None.

dll.voidFunct.restype = None
Douche answered 20/5, 2011 at 14:50 Comment(3)
+1 Setting restype as you state results in None being returned from the functionCoral
Funny enough, in the relevant section of the official documentation this is still not mentioned.Aeroembolism
@Trilarion It is sort of mentioned in restype entry in section 16.16.2.3: "Use None for void, a function not returning anything." I really would have expected to see it listed in the table in section 16.16.1.4, however.Wyrick
C
7

That's undefined behaviour. You are asking ctypes to read a return value that is simply not there. It reads something off the stack, but what comes back is ill-defined.

Coral answered 20/5, 2011 at 14:47 Comment(0)
O
0

Building on the answer from Boaz Yaniv above:

===QUOTE===

In short, you defined voidFunct() as a function returning int, not void, and Python expects it to return an int.

...

What you should probably do, is to explicitly state a return value type of None:

dll.voidFunct.restype = None

===UNQUOTE===

If one looks into the internals of C, integer return values are returned to the caller via the ax/eax register, rather than via the stack or similar. So the value being printed out is not exactly random, but the value that happens to be in the ax register when the function returned.

In this case, the most recent use of the ax/eax register was the (unused) return value from the printf() statement - which is the number of bytes written to the console by the printf() function. (Note that the length of the string "voidFunct called!!!\n" is 20, not 17. We can be fairly sure that C program mentioned above is not exactly verbatim of what was run)

Olla answered 29/5 at 15:43 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.