Types and Type Safety¶
Shared libraries don't contain any information about the types of a function's arguments or its return type. It doesn't even count how many arguments a function takes - you just get seg-faultsA fatal error raised when trying to read/write memory that isn't (or no longer is) owned by Python. and memory errors if you get it wrong.
ctypes
allows you to set the type information for functions (accessible via
function.argtypes
and function.restype
) but it means you have to
effectively copy and translate function prototypes from C into Python (which is
both mind-numbing and error-prone).
cslug automates the above by scanning your C source code for
function definitions, dumping the information into a json file with the same
name as your shared library (first argument to CSlug
) then
setting the type information for each function on loading the library (invoked
by accessing slug.dll
). This provides some degree of implicit type safety
and casting for the basic types:
Python Type |
Equivalent C Type(s) |
---|---|
|
|
|
|
Single character |
|
Arbitrary length |
|
Single character |
|
Arbitrary length |
|
|
Type Checking¶
You don't need to do anything to enable type checking - it's automatic.
The rest of this page is purely to see type checking in action.
Put the following function into typing.c
.
double reciprocal(double x) {
return 1.0 / x;
}
Now, to compile it:
from cslug import CSlug
slug = CSlug("typing.c")
And run it. Floats pass in and out of C as we'd expect them to:
>>> slug.dll.reciprocal(2.0)
0.5
Integers and any other type which can be safely converted to float are automatically converted without complaint like they are in Python:
>>> slug.dll.reciprocal(4)
.25
>>> from fractions import Fraction
>>> slug.dll.reciprocal(Fraction(1, 3))
3.0
But anything else gives a TypeError
as we'd expect:
>>> slug.dll.reciprocal("hello")
ctypes.ArgumentError: argument 1: <class 'TypeError'>: wrong type
>>> slug.dll.reciprocal()
TypeError: this function takes at least 1 argument (0 given)
To see what it's like without the safety net, remove the type information from
slug.dll.reciprocal()
and try calling it again:
slug.dll.reciprocal.restype = int # The default return type.
slug.dll.reciprocal.argtypes = None # Unknown arguments.
Pointer Types¶
Type checking for pointersThe memory address of an object stored in another variable. on the other hand is very minimal. A wchar_t
*
correlates to str
in Python (and is type-checked accordingly) and a
char *
correlates to bytes
(including bytearray
and
memoryview
). See Strings and Bytes for working with string
types. All other pointer types are reduced to void *
.