How does Python assign and retrieve a DLL's global variable? [duplicate] - python

I'd like to map an int value pbs_errno declared as a global in the library libtorque.so using ctypes.
Currently I can load the library like so:
from ctypes import *
libtorque = CDLL("libtorque.so")
and have successfully mapped a bunch of the functions. However, for error checking purposes many of them set the pbs_errno variable so I need access to that as well. However if I try to access it I get:
>>> pytorque.libtorque.pbs_errno
<_FuncPtr object at 0x9fc690>
Of course, it's not a function pointer and attempting to call it results in a seg fault.
It's declared as int pbs_errno; in the main header and extern int pbs_errno; in the API header files.
Objdump shows the symbol as:
00000000001294f8 g DO .bss 0000000000000004 Base pbs_errno

There's a section in the ctypes docs about accessing values exported in dlls:
http://docs.python.org/library/ctypes.html#accessing-values-exported-from-dlls
e.g.
def pbs_errno():
return c_int.in_dll(libtorque, "pbs_errno")

Related

Python ctypes using C++ members

I'm trying using C++ in python.So ım trying use c++ members with python.
There my try.cpp file ..
extern "C" int test(){
string a="Test!!";
int b = 5;}
Also dll.py ..
from ctypes import cdll
import os
fullpath = os.path.abspath('try.dll')
mydll = cdll.LoadLibrary(fullpath)
CALL = mydll.test()
Basically, ı just want using C++ members like ;
CALL = mydll.test()
print CALL.a # Output : Test!!
print CALL.b # Output : 5
Any advice? I just want use directly C++ members, but im not sure is that posible .. confused
Python's C API doesn't support C++ members directly. To do what you are proposing requires a 3-step process that is implemented for you in the SWIG program.
Create a python reference to a void* pointer that is actually a C++ object, and expose this via the C api.
For each member/ function of the C++ class, create a C function, exposed to Python, that uses the void * pointer and calls (Object *)->function()
Create a python class that holds the python reference to the C++ object, and that has methods and functions that call the corresponding C api functions that, in turn, pass their arguments to the C++ methods
Translation: use SWIG!

Python ctype directly call a function with raw offset

Is it possible to call a RAW function pointer inside python?
for example:
ctypes.windll.kernel32.GetModuleHandleA(None)
will call the API, Python resolves the DLL + Function pointer to make it work. but if I have a raw function pointer, for example 0xDEADBEEF (which corresponds to the function header) how do I create a funciton instance passing this raw pointer?
I can't just export the function since its located on a compiled executable, but I want to be able to do something like this:
To make it clear... in C++ I can call RAW function with something like this:
#define myfunction ((void(*)(int a, int b, int c)) 0x00402383)
myfunction(1, 2, 3);
I python I wanted to make something similar, maybe using ctypes library?
I've digged inside the library but I couldn't find how they initialize the function instance.
Notes:
The python engine is embedded inside a DLL.
The DLL is injected into the process I want to call the function address.
If the function is located in a compiled executable, then you can't, neither in C++ because you'll get an access violation. You can't call functions from another process.
If you have C++ knowledge then create a DLL and inject it into the executable. You'll be able to call it.
Since you've already injected your DLL into the target process, it seems to be possible to achieve what you want using ctypes.
>>> functype = ctypes.CFUNCTYPE(ctypes.c_int, ctypes.c_int, ctypes.c_int)
>>> func = functype(raw_address)
>>> func
<CFunctionType object at 0x1006816d0>

Access methods not exposed in the method mapping table with ctypes

The method mapping table is an array of PyMethodDef structures,
struct PyMethodDef {
char *ml_name;
PyCFunction ml_meth;
int ml_flags;
char *ml_doc;
};
where the ml_name is the name of the functions accessed in the interpreter (i.e. gc.collect()), ml_meth is the address of the function described in the previous section, ml_flags indicates which of the signatures ml_meth is using and ml_doc is the docstring for the function.
Now, say I want to access from within the gcmodule.c gc_list_append which is not exposed by the gc interface.
I've tried the following:
pythonapi.PyImport_ImportModule("gcmodule")
or
pythonapi.PyImport_ImportModule(ctypes.c_wchar("gcmodule"))
Hoping that the reference returned can be used to access unexposed methods, but in both cases I get errors:
ImportError: No module named 'g'
or
TypeError: one character unicode string expected
Any idea how an unexposed function or data structures can be accessed via ctypes/pythonapi?
PyImport_ImportModule imports a module as named by the const char * argument. It calls PyImport_Import, which in turn calls __builtin__.__import__ in PY2. Calling it with the C string "gc" returns a reference to sys.modules['gc'] if it exists, else the interpreter creates the module by calling initgc , which it finds in _PyImport_Inittab. The gc module's init function calls Py_InitModule4, which loops over the GcMethods table to add methods to the module dict.
Every global definition you see in gcmodule.c that's marked static is only visible within that compilation unit at the system level, i.e. it doesn't have external linkage. Commonly an extension module only exports the name of the PyMODINIT_FUNC, but several of the built-in modules in CPython also export public APIs such as PyObject_GC_Track.
On Windows, exporting a symbol from a DLL by name or ordinal requires the extra step of declaring it in a .def file or with the modifier __declspec(dllexport). In CPython that gets applied via the macros PyAPI_FUNC (pyport.h), PyAPI_DATA, and PyMODINIT_FUNC. For example, objimpl.h declares PyAPI_FUNC(void) PyObject_GC_Track(void *).
Declaring a symbol static is namespace management. However, if you can get the address of a function somehow, you can certainly call it with a ctypes function pointer. Finding the address is the issue. ctypes uses the standard POSIX dlsym and Windows GetProcAddress functions to look up exported symbols, which won't help you here. You may be able to access function pointers referenced directly or indirectly by CPython objects, since id returns the object base address.
The following isn't directly related to your problem, but I'm including it for general interest.
On a POSIX system that loads extension modules with dlopen, you can specify RTLD_GLOBAL to merge the dynamic symbols into the global namespace. For example, the _ctypes extension module is linked from multiple object files and needs several extern symbols, such as PyCData_set. You can tweak the import to have PyCData_set accessible globally (e.g. via ctypes.pythonapi):
>>> import sys, DLFCN
>>> sys.setdlopenflags(DLFCN.RTLD_GLOBAL | DLFCN.RTLD_NOW)
>>> import ctypes
>>> hasattr(ctypes.pythonapi, 'PyCData_set')
True
Of course, that won't work on Windows. The proper way for an extension module to make a C API available is by using a PyCapsule, such as datetime.datetime_CAPI (datetimemodule.c).

How to specify a non default type when calling a FFmpeg library using ctypes

I am calling an FFMPEG library called avformat_alloc_context() that returns a pointer to type AVFormatContext. The structure AVFormatContext is defined in the avformat library.
Obviously; this is not one ctypes default types and results in an error when I try to pass a reference to it to another ffmpeg library further down in my code.
Is there a way to add in the the classes defined inside of the library ? I read through what documentation I could find online and was not able to find a good answer to this question.
You need to first of all translate the AVFormatContext struct into a ctypes declaration. You do this by deriving from the Structure class.
Then you need to specify that the avformat_alloc_context function returns a pointer to that struct. You assign restype to do so:
avformat_alloc_context.restype = POINTER(AVFormatContext)
Then you can call the function like this:
contextPtr = avformat_alloc_context()
To get at the contents of the pointer, read the contents attribute:
context = contextPtr.contents
And don't forget to call avformat_free_context() when you have finished with the pointer.
This information is all covered in more detail in the ctypes documentation.

Import constants from .h file into python

I've been looking for a simple answer to this question, but it seems that I can't find one. I would prefer to stay away from any external libraries that aren't already included in Python 2.6/2.7.
I have 2 c header files that resemble the following:
//constants_a.h
const double constant1 = 2.25;
const double constant2 = -0.173;
const int constant3 = 13;
...
//constants_b.h
const double constant1 = 123.25;
const double constant2 = -0.12373;
const int constant3 = 14;
...
And I have a python class that I want to import these constants into:
#pythonclass.py
class MyObject(object):
def __init(self, mode):
if mode is "a":
# import from constants_a.h, like:
# self.constant1 = constant1
# self.constant2 = constant2
elif mode is "b":
# import from constants_b.h, like:
# self.constant1 = constant1
# self.constant2 = constant2
...
I have c code which uses the constants as well, and resembles this:
//computations.c
#include <stdio.h>
#include <math.h>
#include "constants_a.h"
// do some calculations, blah blah blah
How can I import the constants from the header file into the Python class?
The reason for the header files constants_a.h and constants_b.h is that I am using python to do most of the calculations using the constants, but at one point I need to use C to do more optimized calculations. At this point I am using ctypes to wrap the c code into Python. I want to keep the constants away from the code just in case I need to update or change them, and make my code much cleaner as well. I don't know if it helps to note I am also using NumPy, but other than that, no other non-standard Python extensions. I am also open to any suggestions regarding the design or architecture of this program.
In general, defining variables in C header file is poor style. The header file should only declare objects, leaving their definition for the appropriate ".c" source code file.
One thing you may want to do is to declare the library-global constants like extern const whatever_type_t foo; and define (or "implement") them (i.e. assigning values to them) somewhere in your C code (make sure you do this only once).
Anyway, let's ignore how you do it. Just suppose you've already defined the constants and made their symbols visible in your shared object file "libfoo.so". Let us suppose you want to access the symbol pi, defined as extern const double pi = 3.1415926; in libfoo, from your Python code.
Now you typically load your object file in Python using ctypes like this:
>>> import ctypes
>>> libfoo = ctypes.CDLL("path/to/libfoo.so")
But then you'll see ctypes thinks libfoo.pi is a function, not a symbol for constant data!
>>> libfoo.pi
<_FuncPtr object at 0x1c9c6d0>
To access its value, you have to do something rather awkward -- casting what ctypes thinks is a function back to a number.
>>> pi = ctypes.cast(foo.pi, ctypes.POINTER(ctypes.c_double))
>>> pi.contents.value
3.1415926
In C jargon, this vaguely corresponds to the following thing happening: You have a const double pi, but someone forces you to use it only via a function pointer:
typedef int (*view_anything_as_a_function_t)(void);
view_anyting_as_a_function_t pi_view = π
What do you do with the pointer pi_view in order to use the value of pi? You cast it back as a const double * and dereference it: *(const double *)(pi_view).
So this is all very awkward. Maybe I'm missing something but this I believe is by design of the ctypes module -- it's there chiefly for making foreign function calls, not for accessing "foreign" data. And exporting pure data symbol in a loadable library is arguably rare.
And this will not work if the constants are only C macro definitions. There's in general no way you can access macro-defined data externally. They're macro-expanded at compile time, leaving no visible symbol in the generated library file, unless you also export their macro values in your C code.
I recommend using regular expressions (re module) to parse the information you want out of the files.
Building a full C parser would be huge, but if you only use the variables and the file is reasonably simple/predictable/under control, then what you need to write is straightforward.
Just watch out for 'gotcha' artifacts such as commented-out code!
I would recommend using some kind of configuration file readable by both Python and C program, rather than storing constant values in headers. E.g. a simple csv, ini-file, or even your own simple format of 'key:value' pairs. And there will be no need to recompile the C program every time you'd like to change one of the values :)
I'd up-vote emilio, but I'm lacking rep!
Although you have requested to avoid other non-standard libraries, you may wish to take a look at Cython (Cython: C-Extensions for Python www.cython.org/), which offers the flexibility of Python coding and the raw speed of execution of C/C++-compiled code.
This way you can use regular Python for everything, but handle the expensive elements of code using its built-in C-types. You can then convert your Python code into .c files too (or just wrap external C-libraries themselves. ), which can then be compiled into a binary. I've achieved up to 10x speed-ups doing so for numerical routines. I also believe NumPy uses it.

Categories