使用Python和ctypes将对象作为参数传递时读取违规

时间:2016-06-17 11:11:30

标签: python c++ ctypes

我正在尝试使用ctypes将用C ++编写的现有硬件API公开给Python。现有API创建通信套接字对象,然后通过引用将其传递给使用它与硬件通信的其他组件。完整的API中有很多无关的细节,所以我把它剥离回一个简单的例子,它表现出我在整个系统中看到的同样的失败。我不是专家程序员,也不是Python的新手,所以我怀疑我做的事情很傻。本机C ++代码包含以下内容:

通讯

comms.h

#ifndef COMMS_H
#define COMMS_H

#include <iostream>

using std::string;
using std::uint32_t;
using std::cout;
using std::endl;

class Comms
{
public:
    Comms();
    void getStatus();

private:
    string   m_addr;
    uint32_t m_port;
};

#endif // COMMS_H

comms.cpp

#include "comms.h"

Comms::Comms()
{
    m_addr = "192.168.2.1";
    m_port = 5000;
}

void Comms::getStatus()
{
    cout << "Comms object handle is " << this << endl;
    cout << "Comms address is " << m_addr << endl;
    cout << "Comms port is " << m_port << endl << endl;
}

// Extern methods for Python binding via ctypes
extern "C" {
    Comms* Comms_new(){ return new Comms(); }
    void Comms_getStatus(Comms* comms){ comms->getStatus(); }
}

UserApp 类,它采用通信类型的参数,通过引用传递。

userapp.h

#ifndef USERAPP_H
#define USERAPP_H

#include <iostream>
#include "../Comms/comms.h"

using std::cout;
using std::endl;

class UserApp
{
public:
    UserApp(Comms *theComms);
};

#endif // USERAPP_H

userapp.cpp

#include "userapp.h"

UserApp::UserApp(Comms *theComms)
{    
    cout << "New UserApp created, Comms object passed by reference" << endl;
    cout << "UserApp handle is " << this << endl;
    cout << "Comms handle is " << theComms << endl << endl;
    theComms->getStatus();
}

// Extern methods for Python binding via ctypes
extern "C" {
    UserApp* UserApp_new(Comms *theComms){ return new UserApp(theComms); }
}

在C ++中这一切都运行正常,我有一个简单的main.cpp(在Qt中运行),每个类都有一个实例...

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    Comms myComms;
    myComms.getStatus();

    UserApp myUserApp(&myComms);

    return a.exec();
}

....并且输出与我期望的一致:

Comms object handle is 0x28fea0
Comms address is 192.168.2.1
Comms port is 5000

New UserApp created, Comms object passed by reference
UserApp handle is 0x28fe9f
Comms handle is 0x28fea0

Comms object handle is 0x28fea0
Comms address is 192.168.2.1
Comms port is 5000

要将所有这些绑定到Python,我已经基于上面的内容创建了DLL并编写了以下类来镜像C ++版本:

Comms.py

from ctypes import *
import os
commsLib = cdll.LoadLibrary("Comms.dll")

class Comms(object):
    def __init__(self):
        self.obj = commsLib.Comms_new()  

    def getStatus(self):
        commsLib.Comms_getStatus(self.obj)

UserApp.py

from ctypes import *
import os

UserAppLib = cdll.LoadLibrary("UserApp.dll")

class UserApp(object):
    def __init__(self, comms):
        self.obj = UserAppLib.UserApp_new(comms)    

我的Python顶级如下,再次尝试反映我在C ++中所做的事情:

from ctypes import *

from Comms  import Comms
from UserApp import UserApp

myComms = Comms()
myComms.getStatus()

myUserApp = UserApp(py_object(myComms))

Python输出如下。我可以看到myComms的创建看起来没问题,但是当我尝试将其传递给myUserApp时,myComms对象引用并不会占用,并且代码会引发访问冲突OSError。我做错了什么?

Comms object handle is 0x183048
Comms address is 192.168.2.1
Comms port is 5000

New UserApp created, Comms object passed by reference
UserApp handle is 0x183078
Comms handle is 0x568bb0

Comms object handle is 0x568bb0
Traceback (most recent call last):
  File "wrapper_api_UnitTest.py", line 9, in <module>
    myUserApp = UserApp(py_object(myComms))
  File "c:\Temp\ctypes_test\python\UserApp.py", line 8, in __init__
    self.obj = UserAppLib.UserApp_new(comms)    
OSError: exception: access violation reading 0xFFFFFFF6

0 个答案:

没有答案