首页 > 解决方案 > python ctypes中指向C++自定义类实例的截断指针地址

问题描述

我正在尝试使用 ctypes 从 python 访问 C++ 类。用于访问 C++ 功能的包装函数在 DLL 中公开。

我有一个 C++ 数据类。该类的一个实例是在从 python 到 C++ 的第一个函数调用中创建的,并传回指向该实例的指针。第二个 python 函数调用将指针作为 arg 并打印它的一些数据。

问题是指针地址被截断。在创建类实例之后打印指针时,它看起来像“000001A05127F110”。然后当指针在第二个函数调用中在 C++ 中再次打印时,它看起来像“000000005127F110”。

我正在使用 python 3.6.8 x64,MSVC x64。

我已经尝试将argtypes和设置restypes为各种 ctypes 内置类型,但它并没有解决问题。

有趣的是,这是我第二次尝试这样做。过去,我在这里使用的相同解决方案在相同(或类似)情况下运行良好。

数据包装器.h

#include <string>

class DataWrapper
{
public:

    DataWrapper()
    {
        m_temp = std::string("hi");
    }

    virtual ~DataWrapper()
    {
        std::cout << "Deleting" << std::endl;
    }

    std::string m_temp;

};

包装器.cpp

#include <iostream>
#include <string>

#include "cogitant/data_wrapper.h"

#define DLLEXPORT extern "C" __declspec(dllexport)

DLLEXPORT void checkData(DataWrapper * d)
{
    std::cout << d << std::endl;
    //std::cout << d->m_temp << std::endl;
}

DLLEXPORT DataWrapper * makeData()
{
    DataWrapper * d = new DataWrapper();
    std::cout << d << std::endl;
    return d;
}

主文件

import ctypes

CPP_LIB_DLL_LOC = "<my path>/data_wrapper.dll"
LIB = ctypes.cdll.LoadLibrary(CPP_LIB_DLL_LOC)

def main():
    print("Starting. . .")

    #make new data class
    make_func = LIB.makeData
    make_func.argtypes = []
    make_func.restypes = ctypes.c_void_p
    dataclass = make_func()
    print(dataclass)
    print(type(dataclass ))

    #check the dataclass pointer is valid
    check_func = LIB.checkData
    check_func.restypes = None
    check_func.argtypes = [ctypes.c_void_p]
    check_func(dataclass)

    print("Finished.")

if __name__ == "__main__":
    main()

这是python输出:

Starting. . .
000001ED0E612320
241247008
<class 'int'>
000000000E612320
Finished.

我希望这两个地址是相同的。如果我取消注释该行,wrapper.cpp则会看到以下错误:

  File "<my path>/python/main.py", line 21, in main
    check_func(dataclass)
OSError: exception: access violation reading 0x000000000E612320

标签: pythonc++ctypes

解决方案


restype不是restypes

这解决了我遇到的问题。

可以确认:

LIB.makeData.fuck_ctypes

确实会导致错误。


推荐阅读