Problem in PyArg_ParseTuple on python 2.5.2 with AIX

A

abhi

Hi,
I am facing a problem using PyArg_ParseTuple() in my C-API
extension. Here is a small repro of the function:

static PyObject *parsetuple_test(PyObject *self, PyObject *args)
{
SQLUSMALLINT param_no = 0;
PyObject *py_obj = NULL;

if (!PyArg_ParseTuple(args, "Oi", &py_obj, &param_no)){

return NULL;
}
printf("%d\n", param_no);
return NULL;
}

This function works fine and prints the correct value passed
(param_no) when I test it on Linux or Windows. However, it always
prints 0 (initial value defined in function) when I run it on AIX.

I think the problem is with "Oi" argument, if I replace that with "OO"
and specifically convert it integer/sqlsmallint. It works fine on AIX,
but I want to use "i" and not "O".

Any ideas on what is the reason behind the problem and how to fix
this?

Thanks,
Abhigyan
 
J

John Machin

Hi,
    I am facing a problem using PyArg_ParseTuple() in my C-API
extension. Here is a small repro of the function:

static PyObject *parsetuple_test(PyObject *self, PyObject *args)
{
        SQLUSMALLINT param_no = 0;

Sorry, my crystal ball is on the fritz. What is SQLUSMALLINT on
Windows/Linux/AIX?
What does
printf("%d %d %d\n", sizeof(SQLUSMALLINT), sizeof(int), sizeof
(long));
give you on each platform?
        PyObject *py_obj = NULL;

        if (!PyArg_ParseTuple(args, "Oi", &py_obj, &param_no)){

                return NULL;
        }
        printf("%d\n", param_no);
        return NULL;

}

This function works fine and prints the correct value passed
(param_no) when I test it on Linux or Windows. However, it always
prints 0 (initial value defined in function) when I run it on AIX.

Consider that 0 could have been plucked out of the air and has nothing
to do with the initial value of param_no. Try initialising it to
something distinctive, like 0xfedcba98. Use %08x format in the printf
rather than %d.

I think the problem is with "Oi" argument, if I replace that with "OO"
and specifically convert it integer/sqlsmallint. It works fine on AIX,
but I want to use "i" and not "O".

Any ideas on what is the reason behind the problem and how to fix
this?

I jump-started the crystal ball from the over-head tram wire and saw
this: """SQLSMALLINT is 16 bits on all platforms, int/long is 32 bits
on all platforms, first 2 are little-endian, AIX is bigendian, the "i"
format expects SIGNED int /long, so param_no is getting (win:x,
linux:x, aix:0) and the next 16 bits in memory are getting trashed
with (win:0, linux:0, aix:x) (when x is your input smallish integer)
and luckily this trashing didn't cause a crash. You can receive the
result from the function in an int/long then have code to reject it if
it won't fit into a SQLUSMALLINT, and cast it otherwise. If you don't
care about overflow (NOT recommended), just use "H" format instead if
"i" format"""

Could be wrong, really shouldn't subject precision instruments to 415V
DC, only OPs :)

N.B. to detect endianness : use print sys.byteorder

HTH,
John
 
A

abhi

Sorry, my crystal ball is on the fritz. What is SQLUSMALLINT on
Windows/Linux/AIX?
What does
    printf("%d %d %d\n", sizeof(SQLUSMALLINT), sizeof(int), sizeof
(long));
give you on each platform?




Consider that 0 could have been plucked out of the air and has nothing
to do with the initial value of param_no. Try initialising it to
something distinctive, like 0xfedcba98. Use %08x format in the printf
rather than %d.





I jump-started the crystal ball from the over-head tram wire and saw
this: """SQLSMALLINT is 16 bits on all platforms, int/long is 32 bits
on all platforms, first 2 are little-endian, AIX is bigendian, the "i"
format expects SIGNED int /long, so param_no is getting (win:x,
linux:x, aix:0) and the next 16 bits in memory are getting trashed
with (win:0, linux:0, aix:x) (when x is your input smallish integer)
and luckily this trashing didn't cause a crash. You can receive the
result from the function in an int/long then have code to reject it if
it won't fit into a SQLUSMALLINT, and cast it otherwise. If you don't
care about overflow (NOT recommended), just use "H" format instead if
"i" format"""

Could be wrong, really shouldn't subject precision instruments to 415V
DC, only OPs :)

N.B. to detect endianness : use print sys.byteorder

HTH,
John

Hi,
Thanks for the response. If I don't use SQLUSMALLINT and use int
instead, then also I see the same problem.
static PyObject *parsetuple_test(PyObject *self, PyObject *args)
{
int param_no = 0;
.....
.....
}
This also prints out 0 for AIX and actual value passed in other
platforms. If I initialize param_no with some other value (e.g. 90),
it prints out that value.

-
Abhigyan
 
J

John Machin

And the answer was: what?
    Thanks for the response. If I don't use SQLUSMALLINT and use int
instead, then also I see the same problem.
static PyObject *parsetuple_test(PyObject *self, PyObject *args)
 {
        int param_no = 0;
....
....}

This also prints out 0 for AIX and actual value passed in other
platforms. If I initialize param_no with some other value (e.g. 90),
it prints out that value.

Please run the following on AIX with Python 2.5:
import sys
print sys.byteorder, sys.maxint
print sys.version
and tell us the output.

Does the C compiler that you are using for the extension correspond
with whatever is mentioned in sys.version about the C compiler used to
compile Python 2.5?

C code: Please add/change as follows:
int dummy1 = 0xaaaabbbb;
int param_no = 0xccccdddd;
int dummy2 = 0xeeeeffff;
....
printf("%08x %08x %08x\n", dummy1, param_no, dummy2);
printf("%d %d\n", sizeof(int), sizeof(long));

Try this on AIX (a) with no optimisation (b) whatever O level you have
been using.

Try it with (i) small positive input (i) integer > 65535

Take a copy of your extension and cut out everything that is not part
of executing this function i.e. apart from this function (with the
dummies and printfs) you should have only a few includes, a table
defining just 1 callable function, and the minimal module
initialisation code. Check that this cut down version works on Windows
and Linux and still fails on AIX. Then try it without the first ("O")
arg. If it still fails on AIX, lose the first arg. Publish the minimal
failing code, the instructions to build the .so, and a transcript of
the Python interactive session showing calling the function and the
results.

Cheers,
John
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,994
Messages
2,570,222
Members
46,809
Latest member
moe77

Latest Threads

Top