This question already has answers here:
Is it possible to "hack" Python's print function?
(4 answers)
Can we make 1 == 2 true? [duplicate]
(3 answers)
Closed 4 years ago.
Before carrying on any further, I am aware that one should never do this. This question is purely for educational purposes; I undertook this exercise as a means of better understanding python's internals, the ctypes, and how they work.
I am aware that it is relatively easy to change the value of integers in python. Actually, there's a whole lot you can do by messing with the internals. From the C API reference,
The current implementation keeps an array of integer objects for all
integers between -5 and 256, when you create an int in that range you
actually just get back a reference to the existing object. So it
should be possible to change the value of 1. I suspect the behaviour
of Python in this case is undefined. :-)
Considering the value of 1 is cached by CPython, it should be relatively easy (or, at least possible) to do this. After a little digging around, I found ctypes was the way to go. However, most of what I try results in a segfault. I got close by changing the value of 2.
import ctypes
def deref(addr, typ):
return ctypes.cast(addr, ctypes.POINTER(typ))
deref(id(2), ctypes.c_int)[6] = 1
1 + 1 now gives incorrect results (a step in the right direction), but I cannot get it to evaluate to "3":
>>> 1 + 1
1
>>> 1 + 2
1
>>> 1 + 3
[1] 61014 segmentation fault python3.6
I have tried similar things ending in failure with abarnert's internals module. Is there any way to have 1 + 1 evaluate to 3 in python? Or is "1" so all important that there is no way of making this work without segfaulting my interpreter?
Disclaimer: this answer refers to CPython only; I might have also missed the point of the question...
I was able to (kinda) achieve this by writing a Python extension in C.
In Objects/intobject.c there is an info struct PyInt_Type. Its tp_as_number field is a table of operator functions, the nb_add field of which is the addition operator:
// the function in the same file that nb_add points to
static PyObject *
int_add(PyIntObject *v, PyIntObject *w)
...
PyInt_Type is an exposed global variable, and can be retrieved with dlsym in Unix / GetProcAddress in WinAPI:
#include <dlfcn.h>
...
// symbol look-up from the Python extension
void* addr = dlsym(RTLD_DEFAULT, "PyInt_Type");
// pointer to PyInt_Type
PyTypeObject *int_type = addr;
// pointer to int_as_number (PyInt_Type.tp_as_number)
PyNumberMethods *int_funcs = int_type->tp_as_number;
// pointer to int_add (tp_as_number->nb_add)
int_add_orig = int_funcs->nb_add;
// override this with a custom function
int_funcs->nb_add = (binaryfunc)int_add_new;
...
// custom add function
PyObject *int_add_new(PyIntObject *v, PyIntObject *w)
{
long a = PyInt_AS_LONG(v);
long b = PyInt_AS_LONG(w);
// 1 + 1 = 3 special case
if (a == 1 && b == 1) {
return PyInt_FromLong(3);
}
// for all other cases default to the
// original add function which was retrieved earlier
return int_add_orig((PyObject *)v, (PyObject *)w);
}
By preserving all of the original code and internal variables, the new code avoids the previously experienced segfaults:
>>> # load the extension
>>> import [...]
>>> 1 + 1
2
>>> # call the extension function which overloads the add operator
>>> 1 + 1
3
>>> 1 + 0
1
>>> 1 + 2
3
>>> 1 + 3
4
Related
So I've been trying to rewrite a Ruby snippet of code into Python, and I haven't been able to make it work. I reread everything to make sure I did it right, but it still doesn't work. I guess the problem lies in this "translation":
def multiply(k, point = $G)
current = point
binary = k.to_s(2)
binary.split("").drop(1).each do |char|
current = double(current)
current = add(current, point) if char == "1"
end
current
end
This is my translated python version:
def multiply(k, point = G):
current = point
binary = bin(k)
for i in binary[3:]:
current = double(current)
if i == "1":
current = add(current, point)
return current
I believe I didn't quite understand Ruby's concepts of to_s(2) and/or .drop(1).
Could someone tell me what is the best way of translating this Ruby code into Python?
EDIT
So, I'll elaborate just as #Michael Butscher suggested:
I have this Ruby code, which I tried to translate into this Python code. And while the output should be
044aeaf55040fa16de37303d13ca1dde85f4ca9baa36e2963a27a1c0c1165fe2b11511a626b232de4ed05b204bd9eccaf1b79f5752e14dd1e847aa2f4db6a5
it throws an error. Why?
The problem is not in the function you have shown, but in your inverse function. / between integers in Ruby translates as // in Python 3:
Ruby:
3 / 2
# => 1
3.0 / 2
# => 1.5
Python 3:
3 / 2
# => 1.5
3 // 2
# => 1
I am a Python n00b and at the risk of asking an elementary question, here I go.
I am porting some code from C to Python for various reasons that I don't want to go into.
In the C code, I have some code that I reproduce below.
float table[3][101][4];
int kx[6] = {0,1,0,2,1,0};
int kz[6] = {0,0,1,0,1,2};
I want an equivalent Python expression for the C code below:
float *px, *pz;
int lx = LX; /* constant defined somewhere else */
int lz = LZ; /* constant defined somewhere else */
px = &(table[kx[i]][0][0])+lx;
pz = &(table[kz[i]][0][0])+lz;
Can someone please help me by giving me the equivalent expression in Python?
Here's the thing... you can't do pointers in python, so what you're showing here is not "portable" in the sense that:
float *px, *pz; <-- this doesn't exist
int lx = LX; /* constant defined somewhere else */
int lz = LZ; /* constant defined somewhere else */
px = &(table[kx[i]][0][0])+lx;
pz = &(table[kz[i]][0][0])+lz;
^ ^ ^
| | |
+----+----------------------+---- Therefore none of this makes any sense...
What you're trying to do is have a pointer to some offset in your multidimensional array table, because you can't do that in python, you don't want to "port" this code verbatim.
Follow the logic beyond this, what are you doing with px and pz? That is the code you need to understand to try and port.
There is no direct equivalent for your C code, since Python has no pointers or pointer arithmetic. Instead, refactor your code to index into the table with bracket notation.
table[kx[i]][0][lx] = 3
would be a rough equivalent of the C
px = &(table[kx[i]][0][0])+lx;
*px = 3;
Note that in Python, your table would not be contiguous. In particular, while this might work in C:
px[10] = 3; // Bounds violation!
This will IndexError in Python:
table[kx[i]][0][lx + 10] = 3
I have seen people using buffer in different languages for fast input/output in Online Judges. For example this http://www.spoj.pl/problems/INTEST/ is done with C like this:
#include <stdio.h>
#define size 50000
int main (void){
unsigned int n=0,k,t;
char buff[size];
unsigned int divisible=0;
int block_read=0;
int j;
t=0;
scanf("%lu %lu\n",&t,&k);
while(t){
block_read =fread(buff,1,size,stdin);
for(j=0;j<block_read;j++){
if(buff[j]=='\n'){
t--;
if(n%k==0){
divisible++;
}
n=0;
}
else{
n = n*10 + (buff[j] - '0');
}
}
}
printf("%d",divisible);
return 0;
How can this be done with python?
import sys
file = sys.stdin
size = 50000
t = 0
while(t != 0)
block_read = file.read(size)
...
...
Most probably this will not increase performance though – Python is interpreted language, so you basically want to spend as much time in native code (standard library input/parsing routines in this case) as possible.
TL;DR either use built-in routines to parse integers or get some sort of 3rd party library which is optimized for speed.
I tried solving this one in Python 3 and couldn't get it to work no matter how I tried reading the input. I then switched to running it under Python 2.5 so I could use
import psyco
psyco.full()
After making that change I was able to get it to work by simply reading input from sys.stdin one line at a time in a for loop. I read the first line using raw_input() and parsed the values of n and k, then used the following loop to read the remainder of the input.
for line in sys.stdin:
count += not int(line) % k
I have the following DLL ('arrayprint.dll') function that I want to use in Python via ctypes:
__declspec(dllexport) void PrintArray(int* pArray) {
int i;
for(i = 0; i < 5; pArray++, i++) {
printf("%d\n",*pArray);
}
}
My Python script is as follows:
from ctypes import *
fiveintegers = c_int * 5
x = fiveintegers(2,3,5,7,11)
px = pointer(x)
mydll = CDLL('arrayprint.dll')
mydll.PrintArray(px)
The final function call outputs the following:
2
3
5
7
11
2226984
What is the 2226984 and how do I get rid of it? It doesn't look to be the decimal value for the memory address of the DLL, x, or px.
Thanks,
Mike
(Note: I'm not actually using PrintArray for anything; it was just the easiest example I could find that generated the same behavior as the longer function I'm using.)
mydll.PrintArray.restype = None
mydll.PrintArray(px)
By default ctypes assumes the function returns an integral type, which causes undefined behavior (reading a garbage memory location).
I am writing swig bindings for some c functions. One of these functions takes a float**. I am already using cpointer.i for the normal pointers and looked into carrays.i, but I did not find a way to declare a float**. What do you recommend?
interface file:
extern int read_data(const char
*file,int *n_,int *m_,float **data_,int **classes_);
This answer is a repost of one to a related question Framester posted about using ctypes instead of swig. I've included it here in case any web-searches turn up a link to his original question.
I've used ctypes for several projects
now and have been quite happy with the
results. I don't think I've personally
needed a pointer-to-pointer wrapper
yet but, in theory, you should be able
to do the following:
from ctypes import *
your_dll = cdll.LoadLibrary("your_dll.dll")
PFloat = POINTER(c_float)
PInt = POINTER(c_int)
p_data = PFloat()
p_classes = PInt()
buff = create_string_buffer(1024)
n1 = c_int( 0 )
n2 = c_int( 0 )
ret = your_dll.read_data( buff, byref(n1), byref(n2), byref(p_data), byref(p_classes) )
print('Data: ', p_data.contents)
print('Classes: ', p_classes.contents)