Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Help: 64bit python call c and got OSError: exception: access violation writing 0xFFFFFFFF99222A60

4,004 views
Skip to first unread message

Jason Qian

unread,
Jan 22, 2018, 4:15:30 PM1/22/18
to
Hello!

I am using ctypes on Windows to interface with a dll and it works fine
on Linux and windows 32-bit python. But, when using 64-bit python, we got
error "exception: access violation writing 0xFFFFFFFF99222A60".

Checking our server, it seems work without any problem. but the python
gives an error and stop the application.

-- c --
class myPythonAPI
{
public:
myPythonAPI();
int createService(const char* serviceName){ /* run our application*/};
}
extern "C" {
__declspec(dllexport) myPythonAPI* loadInstance(){ return new
myPythonAPI(); }
__declspec(dllexport) int createService(myPythonAPI* obj, const char*
serviceName) { eturn obj->createService(serviceName);
};

-- python --
from ctypes import *
lib = cdll.LoadLibrary('xxxxxxx.dll')

lib.createService.argtypes=[c_int,ctypes.c_char_p]
lib.createService.restype=ctypes.c_int

class myDriver(object):
def init(self):
self.obj = lib.loadInstance()

def create_services(self,servicename):
result=lib.createService(self.obj,servicename)
return result

driver=myDriver()
driver.create_services(b"myExample")

Thanks for the help
Jason

Random832

unread,
Jan 22, 2018, 4:28:32 PM1/22/18
to
On Mon, Jan 22, 2018, at 16:00, Jason Qian via Python-list wrote:
> Hello!
>
> I am using ctypes on Windows to interface with a dll and it works fine
> on Linux and windows 32-bit python. But, when using 64-bit python, we got
> error "exception: access violation writing 0xFFFFFFFF99222A60".

You are treating the obj type (myPythonAPI *) as c_int, which is only 32 bits. You should be using a pointer type instead (ideally you should be using void * and c_void_p, so Python doesn't need the class definition.) Don't forget to set lib.loadInstance.restype as well.

> __declspec(dllexport) myPythonAPI* loadInstance(){ return new
> myPythonAPI(); }
> __declspec(dllexport) int createService(myPythonAPI* obj, const char*
> serviceName) { eturn obj->createService(serviceName);

eryk sun

unread,
Jan 22, 2018, 5:42:54 PM1/22/18
to
On Mon, Jan 22, 2018 at 9:00 PM, Jason Qian via Python-list
<pytho...@python.org> wrote:
>
> I am using ctypes on Windows to interface with a dll and it works fine
> on Linux and windows 32-bit python. But, when using 64-bit python, we got
> error "exception: access violation writing 0xFFFFFFFF99222A60".
>
> from ctypes import *

Try to avoid * imports if it's a public module.

> lib = cdll.LoadLibrary('xxxxxxx.dll')

Just use CDLL directly. cdll.LoadLibrary is pointless, and
`cdll.xxxxxxx` is problematic in some cases because it caches CDLL
instances, which cache function pointers. Also, the ".dll" filename
extension isn't required in Windows.

> lib.createService.argtypes=[c_int,ctypes.c_char_p]
> lib.createService.restype=ctypes.c_int
>
> class myDriver(object):
> def init(self):
> self.obj = lib.loadInstance()

Since you didn't set loadInstance.restype, the result gets truncated
as a C int, the default result type.

I recommend defining an opaque ctypes struct (i.e. no defined fields)
for the C++ class. This provides type safety. Staying strict and
literal on types is more work than using a `void *` everywhere, but it
pays off in terms of easier debugging and more resilient code. A
simple example is that ctypes returns a `void *` result (or gets a
struct field or array item) as a Python integer. Then for any FFI call
that you may have forgotten to define argtypes, ctypes will default to
truncating this integer value as a C int. At best that causes an
immediate crash. At worst it's a subtle bug that corrupts data.

Here's an example implementation with an opaque struct:

import ctypes

lib = ctypes.CDLL('xxxxxxx')

class myPythonAPI(ctypes.Structure):
pass

PmyPythonAPI = ctypes.POINTER(myPythonAPI)

lib.loadInstance.restype = PmyPythonAPI
lib.loadInstance.argtypes = ()

lib.createService.restype = ctypes.c_int
lib.createService.argtypes = (PmyPythonAPI, ctypes.c_char_p)

class myDriver(object):

def init(self):
self.obj = lib.loadInstance()

def create_services(self, servicename):
return lib.createService(self.obj, servicename)

Jason Qian

unread,
Jan 22, 2018, 5:59:52 PM1/22/18
to
Thanks you very much, fixed the problem :)

On Mon, Jan 22, 2018 at 4:28 PM, Random832 <rand...@fastmail.com> wrote:

> On Mon, Jan 22, 2018, at 16:00, Jason Qian via Python-list wrote:
> > Hello!
> >
> > I am using ctypes on Windows to interface with a dll and it works fine
> > on Linux and windows 32-bit python. But, when using 64-bit python, we
> got
> > error "exception: access violation writing 0xFFFFFFFF99222A60".
>
> You are treating the obj type (myPythonAPI *) as c_int, which is only 32
> bits. You should be using a pointer type instead (ideally you should be
> using void * and c_void_p, so Python doesn't need the class definition.)
> Don't forget to set lib.loadInstance.restype as well.
>
> > __declspec(dllexport) myPythonAPI* loadInstance(){ return new
> > myPythonAPI(); }
> > __declspec(dllexport) int createService(myPythonAPI* obj, const char*
> > serviceName) { eturn obj->createService(serviceName);
>
> > lib = cdll.LoadLibrary('xxxxxxx.dll')
> >
> > lib.createService.argtypes=[c_int,ctypes.c_char_p]
> > lib.createService.restype=ctypes.c_int
> >
> > class myDriver(object):
> > def init(self):
> > self.obj = lib.loadInstance()
> --
> https://mail.python.org/mailman/listinfo/python-list
>

Jason Qian

unread,
Jan 22, 2018, 9:42:32 PM1/22/18
to
Thanks for the help,

Jason

On Mon, Jan 22, 2018 at 5:41 PM, eryk sun <ery...@gmail.com> wrote:

> On Mon, Jan 22, 2018 at 9:00 PM, Jason Qian via Python-list
> <pytho...@python.org> wrote:
> >
> > I am using ctypes on Windows to interface with a dll and it works fine
> > on Linux and windows 32-bit python. But, when using 64-bit python, we
> got
> > error "exception: access violation writing 0xFFFFFFFF99222A60".
> >
> > from ctypes import *
>
> Try to avoid * imports if it's a public module.
>
> > lib = cdll.LoadLibrary('xxxxxxx.dll')
>
> Just use CDLL directly. cdll.LoadLibrary is pointless, and
> `cdll.xxxxxxx` is problematic in some cases because it caches CDLL
> instances, which cache function pointers. Also, the ".dll" filename
> extension isn't required in Windows.
>
> > lib.createService.argtypes=[c_int,ctypes.c_char_p]
> > lib.createService.restype=ctypes.c_int
> >
> > class myDriver(object):
> > def init(self):
> > self.obj = lib.loadInstance()
>
> Since you didn't set loadInstance.restype, the result gets truncated
> as a C int, the default result type.
>
> I recommend defining an opaque ctypes struct (i.e. no defined fields)
> for the C++ class. This provides type safety. Staying strict and
> literal on types is more work than using a `void *` everywhere, but it
> pays off in terms of easier debugging and more resilient code. A
> simple example is that ctypes returns a `void *` result (or gets a
> struct field or array item) as a Python integer. Then for any FFI call
> that you may have forgotten to define argtypes, ctypes will default to
> truncating this integer value as a C int. At best that causes an
> immediate crash. At worst it's a subtle bug that corrupts data.
>
> Here's an example implementation with an opaque struct:
>
> import ctypes
>
> lib = ctypes.CDLL('xxxxxxx')
>
> class myPythonAPI(ctypes.Structure):
> pass
>
> PmyPythonAPI = ctypes.POINTER(myPythonAPI)
>
> lib.loadInstance.restype = PmyPythonAPI
> lib.loadInstance.argtypes = ()
>
> lib.createService.restype = ctypes.c_int
> lib.createService.argtypes = (PmyPythonAPI, ctypes.c_char_p)
>
> class myDriver(object):
>
> def init(self):
> self.obj = lib.loadInstance()
>

Jason Qian

unread,
Jan 24, 2018, 4:26:36 PM1/24/18
to
Again, thanks for the help. Everything is working fine after the changes.

Here is one more new issue needs some help.

On c side,

The createService function can pass a callback handler as second
parameter.
Without callback handler, it works fine. But if we add the callback
handler, the application will give a exception due to the pointer of
callback handler = NULL;

Not sure, why the callback handler missed up, when the app calling from
python.

Thanks

-- python

lib.createService.argtypes=[ctypes.c_void_p,ctypes.c_char_p]
lib.createService.restype=ctypes.c_int

def create_services(self,servicename):
result=lib.createService(self.obj,servicename)
return result

--c --

__declspec(dllexport) int createService(void* obj, const char* serviceName)
{
return ((myPythonAPI*)obj)->createService(serviceName);
}

int myPythonAPI::createService(const char* serviceName)
{
//case 1 :
//This works fine
createService(methodname);

//case 2
//This will not working,
InvocationCallback serviceCallback;
createService(methodname, &serviceCallback);
}











On Mon, Jan 22, 2018 at 5:58 PM, Jason Qian <jq...@tibco.com> wrote:

> Thanks you very much, fixed the problem :)
>
> On Mon, Jan 22, 2018 at 4:28 PM, Random832 <rand...@fastmail.com> wrote:
>
>> On Mon, Jan 22, 2018, at 16:00, Jason Qian via Python-list wrote:
>> > Hello!
>> >
>> > I am using ctypes on Windows to interface with a dll and it works
>> fine
>> > on Linux and windows 32-bit python. But, when using 64-bit python, we
>> got
>> > error "exception: access violation writing 0xFFFFFFFF99222A60".
>>
>> You are treating the obj type (myPythonAPI *) as c_int, which is only 32
>> bits. You should be using a pointer type instead (ideally you should be
>> using void * and c_void_p, so Python doesn't need the class definition.)
>> Don't forget to set lib.loadInstance.restype as well.
>>
>> > __declspec(dllexport) myPythonAPI* loadInstance(){ return new
>> > myPythonAPI(); }
>> > __declspec(dllexport) int createService(myPythonAPI* obj, const char*
>> > serviceName) { eturn obj->createService(serviceName);
>>
>> > lib = cdll.LoadLibrary('xxxxxxx.dll')
>> >
>> > lib.createService.argtypes=[c_int,ctypes.c_char_p]
>> > lib.createService.restype=ctypes.c_int
>> >
>> > class myDriver(object):
>> > def init(self):
>> > self.obj = lib.loadInstance()
>> --
>> https://mail.python.org/mailman/listinfo/python-list
>>
>
>

Jason Qian

unread,
Jan 24, 2018, 11:05:32 PM1/24/18
to
Figured it out,

Thanks
0 new messages