Issue 26 in ctypesgen: POINTER/None work around for 64 bit platforms breaks pointer argument parsing

16 views
Skip to first unread message

codesite...@google.com

unread,
Feb 10, 2012, 9:50:17 AM2/10/12
to ctyp...@googlegroups.com
Status: New
Owner: ----
Labels: Type-Defect Priority-Medium

New issue 26 by l...@segv.dk: POINTER/None work around for 64 bit platforms
breaks pointer argument parsing
http://code.google.com/p/ctypesgen/issues/detail?id=26

The following work around in preamble.py seems to break pointer argument
parsing:

def POINTER(obj):
p = ctypes.POINTER(obj)

# Convert None to a real NULL pointer to work around bugs
# in how ctypes handles None on 64-bit platforms
if not isinstance(p.from_param, classmethod):
def from_param(cls, x):
if x is None:
return cls()
else:
return x
p.from_param = classmethod(from_param)

return p

To reproduce the problem:

------ library libptr.so -----------

#include <stdio.h>
#include "ptr.h"

/*
gcc -m64 -fPIC -shared -o libptr.so ptr.c
/usr/local/bin/ctypesgen.py -o ptr.py ptr.h -l ptr
*/

struct private_s {
int dummy;
};

void go(private_t *p) {
if(p == 0)
fprintf(stderr, "p is supposed to contain an address\n");
}

----- interface ptr.h -----------

#ifndef _PTR_H_
#define _PTR_H_

typedef struct private_s* private_t;
void go(private_t *p);

#endif

-------- test program ptrtest.py ----------

#!/usr/bin/env python
from ptr import *
if __name__ == "__main__":
p = private_t()
go(p)


Now running ptrtest.py I get: "p is supposed to contain an address"

but if I change the POINTER function to:
POINTER=ctypes.POINTER
everything works as expected.

This is tested on Ubuntu 11.10 x86_64 with Python 2.7.2+


codesite...@google.com

unread,
Feb 12, 2012, 11:37:21 PM2/12/12
to ctyp...@googlegroups.com

Comment #1 on issue 26 by jame...@gmail.com: POINTER/None work around for
64 bit platforms breaks pointer argument parsing
http://code.google.com/p/ctypesgen/issues/detail?id=26

The example you have there is a typo. The function "go" accepts a pointer
to private_t object, but you instead passed in a private_t object (which
is, itself, a NULL pointer to a private_s object). If you want to pass in a
reference to a private_t object, the example should work. See
http://docs.python.org/library/ctypes.html#ctypes.byref


Here's a corrected example of your program:


-------- test program ptrtest.py ----------

#!/usr/bin/env python
from ptr import *
if __name__ == "__main__":
p = private_t()

go(byref(p))


I'm not sure how your program is working when you use the standard
ctypes.POINTER function.

codesite...@google.com

unread,
Feb 13, 2012, 2:57:16 AM2/13/12
to ctyp...@googlegroups.com

Comment #2 on issue 26 by l...@segv.dk: POINTER/None work around for 64 bit
platforms breaks pointer argument parsing
http://code.google.com/p/ctypesgen/issues/detail?id=26

It's perfectly legal to omit the byref in this case. calling go(p) and
go(byref(p)) gives the same pointer value in the go function. I looked in
the PyCPointerType_from_param function in the python 2.7.2 sources and it
has this comment:

/* If we expect POINTER(<type>), but receive a <type> instance, accept
it by calling byref(<type>).
*/

So, IMHO ctypesgen needs a fix for this.

codesite...@google.com

unread,
Feb 27, 2012, 12:45:28 AM2/27/12
to ctyp...@googlegroups.com
Updates:
Status: Accepted
Cc: r...@sc3d.org

Comment #3 on issue 26 by jame...@gmail.com: POINTER/None work around for

64 bit platforms breaks pointer argument parsing
http://code.google.com/p/ctypesgen/issues/detail?id=26

Thanks for pointing this out, lars! So what we need to do here is teach
ctypesgen to call byref(...) automatically if we receive an object of the
right <type>.

codesite...@google.com

unread,
Mar 21, 2012, 2:20:46 PM3/21/12
to ctyp...@googlegroups.com

Comment #4 on issue 26 by l...@segv.dk: POINTER/None work around for 64 bit
platforms breaks pointer argument parsing
http://code.google.com/p/ctypesgen/issues/detail?id=26

Maybe it would be an idea to also add "if sys.version_info == (2, 5)"
around the POINTER function definition. There is no need for the extra
overhead on working versions of python.

Reply all
Reply to author
Forward
0 new messages