Python ctypes在使用指向类对象的指针调用函数时出错 我的C++ DLL中有两个包装器函数。

Python ctypes在使用指向类对象的指针调用函数时出错 我的C++ DLL中有两个包装器函数。,python,python-3.x,numpy,ctypes,Python,Python 3.x,Numpy,Ctypes,函数CreateObj()生成另一个类的对象并返回指向该对象的指针 在第二个函数DoSomething中,我将先前创建的指针作为第一个参数传递,第二个参数是无符号字符的RGB图像(1200,1200,3) 在python端,我加载DLL,并希望调用两个包装函数,对在python端加载的RGB图像进行一些处理。在从python调用DoSomething的最后一步中,我遇到了一个操作错误 任何帮助都将不胜感激 //The C++ library code class Obj { /*...

函数
CreateObj()
生成另一个类的对象并返回指向该对象的指针 在第二个函数
DoSomething
中,我将先前创建的指针作为第一个参数传递,第二个参数是无符号字符的RGB图像(1200,1200,3)

在python端,我加载DLL,并希望调用两个包装函数,对在python端加载的RGB图像进行一些处理。在从python调用
DoSomething
的最后一步中,我遇到了一个操作错误

任何帮助都将不胜感激

//The C++ library code

class Obj
{
    /*..../*
};

extern "C"
{
#ifdef BUILD_AS_DLL
    __declspec(dllexport)
#endif
    Obj* CreateObj();
    int DoSomething( Obj* ptr,  uint8_t*  t[1200][1200][]);  //ptr was created using CreateObj and second argument is an image array of unsigned char of shape [1200][1200][3]
#ifdef BUILD_AS_DLL
    __declspec(dllexport)
#endif
}
用于调用上述DLL的Python代码

from ctypes import *
import numpy as np
import numpy.ctypeslib as npct
import cv2
    
path = os.path.join(os.getcwd(), "mwe.dll") 
lib = ctypes.CDLL(path) 

create_func = lib.CreateObj
create_func.restype = c_void_p
obj = c_void_p(create_func())

dosomething_func = lib.DoSomething
ucharPtr = npct.ndpointer(dtype=np.uint8, 
                          ndim=3, 
                          shape = (1200,1200,3),
                          flags='CONTIGUOUS') 
dosomething_func.argtype = (c_void_p,
                            ucharPtr)
dosomething_func.restype = c_int

img = cv2.imread("path/to/image")  
img_ctype = byref(img.ctypes.data_as(c_void_p))
dosomething_func(byref(obj), img_ctype)   // ERROR on this line
我犯了一个错误

File "mwe.py", line 24, in <module>
    res = dosomething_func(
OSError: exception: access violation reading 0xFFFFFFFFFFFFFFFF
文件“mwe.py”,第24行,在
res=剂量测定法(
OSError:异常:访问冲突读取0xFFFFFFFFFFFFFF

下面是一个最小的可复制解决方案示例,演示如何将一个小型3D numpy阵列传入和传出函数:

test.cpp:

请注意,
uint8_t*t[1200][1200][
在语法上不正确。变量数组维度必须是第一个,而不是最后一个,这是指针数组,不是8位数据数组

#include <cstdint>
#include <iostream>

using namespace std;

#define API __declspec(dllexport)

class Obj
{
    int m_x;
public:
    Obj(int x): m_x(x) {}
    int get_x() const { return m_x; }
};

extern "C" {

API Obj* CreateObj() {
    return new Obj(5);
}

API int DoSomething(Obj* ptr, uint8_t t[][3][3]) {
    for(uint8_t i=0; i < 3; ++i) {
        for(uint8_t j=0; j < 3; ++j) {
            for(uint8_t k=0; k < 3; ++k) {
                cout << static_cast<uint32_t>(t[i][j][k]) << ' ';
                t[i][j][k] *= 2;
            }
            cout << endl;
        }
        cout << endl;
    }
    return ptr->get_x();
}

}
输出:

0 1 2
3 4 5
6 7 8

9 10 11
12 13 14
15 16 17

18 19 20
21 22 23
24 25 26

result = 5
[[[ 0  2  4]
  [ 6  8 10]
  [12 14 16]]

 [[18 20 22]
  [24 26 28]
  [30 32 34]]

 [[36 38 40]
  [42 44 46]
  [48 50 52]]]

创建一个。你可以实现一个小型的伪C函数,它接受你想要的参数和Python代码,而Python代码实际上是针对它复制失败的,并删除不相关的代码,比如导入一个图像……只需创建一个你想要直接传递的数组。你的Python代码引用了
seg
,而没有定义它。我有addressed您的评论..seg是一个输入错误这是一个最小的工作示例..我制作的DLL包含两个公开的函数
lib.CreateObj
lib.DoSomething
。请重新考虑Downvoteno。实际上,复制错误消息不起作用。理想情况下,将您实际编写的DLL代码还原为最小代码进行复制重新键入语法不正确的部分代码没有帮助。
0 1 2
3 4 5
6 7 8

9 10 11
12 13 14
15 16 17

18 19 20
21 22 23
24 25 26

result = 5
[[[ 0  2  4]
  [ 6  8 10]
  [12 14 16]]

 [[18 20 22]
  [24 26 28]
  [30 32 34]]

 [[36 38 40]
  [42 44 46]
  [48 50 52]]]