ctypes - python2.7.3 vs python3.2.3

R

Rolf

ctypes works as I would expect with python2.7.3.

However, when I upgrade to python3.2.3 things don't seem to work right. Look below for details.

I am not sure where I am going wrong.

Shared Library
==============
#include <stdint.h>
#include <string.h>

extern "C"
{
int main();
uint32_t myfunction (char **);
}

uint32_t myfunction (char ** _mydata)
{
char mydata[16];

strcpy(mydata, "Hello Dude!");

*_mydata = mydata;

return 0;
}

int main()
{
return 0;
}

Python 2.7.3 which works as I would expect
==========================================
python2.7 -V
Python 2.7.3
cat py27.py
#!/usr/bin/env python2.7

from __future__ import print_function
from __future__ import unicode_literals

from ctypes import *

lib = CDLL('libtest.so')
o_result = c_char_p()
lib.myfunction(pointer(o_result))
print(repr(o_result.value))
./py27.py
'Hello Dude!'

Python 3.2.3 return string gets mangled
=======================================
python3 -V
Python 3.2.3
cat py3.py
#!/usr/bin/env python3

from ctypes import *

lib = CDLL('libtest.so')
o_result = c_char_p()
lib.myfunction(pointer(o_result))
print(repr(o_result.value))
b'\xd8\xb0y\to Dude!'

Every time I run it, I get a different set of values.
 
M

MRAB

ctypes works as I would expect with python2.7.3.

However, when I upgrade to python3.2.3 things don't seem to work right. Look below for details.

I am not sure where I am going wrong.

Shared Library
==============
#include <stdint.h>
#include <string.h>

extern "C"
{
int main();
uint32_t myfunction (char **);
}

uint32_t myfunction (char ** _mydata)
{
char mydata[16];

strcpy(mydata, "Hello Dude!");

*_mydata = mydata;

return 0;
}

int main()
{
return 0;
}
[snip]
What you're doing in 'myfunction' looks wrong to start with. It's
returning the address of the local array 'mydata' which allocated on
the stack when the function is entered. When the function is left it's
deallocated, so the address becomes a dangling pointer. That it gave a
reasonable result with Python 2.7.3 is down to pure luck.
 
J

Jan Kuiken

In said:
uint32_t myfunction (char ** _mydata)
{
char mydata[16];
strcpy(mydata, "Hello Dude!");
*_mydata = mydata;
return 0;
}

mydata is an auto variable, which goes out of scope when myfunction()
exits. *_mydata ends up pointing to garbage.

I'm not completely sure, but i think this can be solved by using:

static char mydata[16];

(Btw.: I don't know why you use char ** _mydata, i would use
char * _mydata, but then again, i'm not very familiar with
ctypes)

Jan Kuiken
 
J

John Gordon

In said:
uint32_t myfunction (char ** _mydata)
{
char mydata[16];
strcpy(mydata, "Hello Dude!");
*_mydata = mydata;
return 0;
}

mydata is an auto variable, which goes out of scope when myfunction()
exits. *_mydata ends up pointing to garbage.
I'm not completely sure, but i think this can be solved by using:
static char mydata[16];

That will solve the immediate problem, however it makes myfunction()
non-reentrant.
(Btw.: I don't know why you use char ** _mydata, i would use
char * _mydata, but then again, i'm not very familiar with
ctypes)

He uses char **_mydata because he wants myfunction()'s caller to see the
new value of _mydata, which it wouldn't if it were just char *_mydata.
 

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,965
Messages
2,570,148
Members
46,710
Latest member
FredricRen

Latest Threads

Top