python - 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
解决方案
它restype
不是restypes
。
这解决了我遇到的问题。
可以确认:
LIB.makeData.fuck_ctypes
确实会导致错误。
推荐阅读
- ios - 使用发布者过滤字符串字段中的数字
- postgresql - Postgres unnest with points
- opengl - 尝试编译已弃用的 OpenGL 函数时,如何使编译器标记错误?
- streaming - 将 m3u8 重新流式传输到流服务
- excel - VBA 的新功能:运行时错误“1004”。应用程序定义或操作定义的错误
- java - 打印简化的除法形式
- javascript - 在 RestApi 日期的响应中添加一天
- firebase - 我如何知道谁更改了我的云功能
- ocl - 如何在 OCL 中进行分组?
- omnet++ - Omnet++ 和 Inet 4 及以上版本是否支持无线节点的多无线电接口