14.14.1.18 Accessing values exported from dlls
Sometimes, a dll not only exports functions, it also exports
variables. An example in the Python library itself is the
Py_OptimizeFlag , an integer set to 0, 1, or 2, depending on the
-O or -OO flag given on startup.
ctypes can access values like this with the in_dll class
methods of the type. pythonapi ?s a predefined symbol giving
access to the Python C api:
>>> opt_flag = c_int.in_dll(pythonapi, "Py_OptimizeFlag")
>>> print opt_flag
c_long(0)
>>>
If the interpreter would have been started with -O, the sample
would have printed c_long(1) , or c_long(2) if -OO would have
been specified.
An extended example which also demonstrates the use of pointers
accesses the PyImport_FrozenModules pointer exported by Python.
Quoting the Python docs: This pointer is initialized to point to an
array of ``struct _frozen`` records, terminated by one whose members
are all NULL or zero. When a frozen module is imported, it is searched
in this table. Third-party code could play tricks with this to provide
a dynamically created collection of frozen modules.
So manipulating this pointer could even prove useful. To restrict the
example size, we show only how this table can be read with
ctypes :
>>> from ctypes import *
>>>
>>> class struct_frozen(Structure):
... _fields_ = [("name", c_char_p),
... ("code", POINTER(c_ubyte)),
... ("size", c_int)]
...
>>>
We have defined the struct _frozen data type, so we can get the
pointer to the table:
>>> FrozenTable = POINTER(struct_frozen)
>>> table = FrozenTable.in_dll(pythonapi, "PyImport_FrozenModules")
>>>
Since table is a pointer to the array of struct_frozen
records, we can iterate over it, but we just have to make sure that
our loop terminates, because pointers have no size. Sooner or later it
would probably crash with an access violation or whatever, so it's
better to break out of the loop when we hit the NULL entry:
>>> for item in table:
... print item.name, item.size
... if item.name is None:
... break
...
__hello__ 104
__phello__ -104
__phello__.spam 104
None 0
>>>
The fact that standard Python has a frozen module and a frozen package
(indicated by the negative size member) is not wellknown, it is only
used for testing. Try it out with import __hello__ for example.
Release 2.5.2, documentation updated on 21st February, 2008.
See About this document... for information on suggesting changes.
|