简体   繁体   English

ctypes 在使用指向 class object 的指针调用 function 时给出错误

[英]ctypes giving error on calling function with pointer to class object

I have two wrapper functions in my C++ DLL.我的 C++ DLL 中有两个包装函数。

The function CreateObj() makes an object of some other class and returns a pointer to the object In the second function DoSomething I pass the previously created pointer as first argument and the second argument is a RGB image (1200, 1200,3) of unsigned chars. The function CreateObj() makes an object of some other class and returns a pointer to the object In the second function DoSomething I pass the previously created pointer as first argument and the second argument is a RGB image (1200, 1200,3) of unsigned字符。

On the python side I load the DLL and want to call the two wrapper functions to do some processing on a RGB image that I have loaded on the python side.在 python 端,我加载 DLL 并想调用两个包装函数对我在 python 端加载的 RGB 图像进行一些处理。 I am getting an OSError in the very last step of calling DoSomething from python.在从 python 调用DoSomething的最后一步中,我遇到了 OSError。

Any help will be greatly appreciated.任何帮助将不胜感激。

//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
}

The Python code for calling the above DLL调用上述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

I get error我收到错误

File "mwe.py", line 24, in <module>
    res = dosomething_func(
OSError: exception: access violation reading 0xFFFFFFFFFFFFFFFF

Here's a minimal reproducible example of a solution demonstrating passing a small 3D numpy array into and back out of a function:这是一个解决方案的最小可重现示例,该示例演示了将小型 3D numpy 阵列传入和传出 function 的解决方案:

test.cpp:测试.cpp:

Note that uint8_t* t[1200][1200][] was syntactically incorrect.请注意, uint8_t* t[1200][1200][]在语法上不正确。 The variable array dimension must be first, not last, and this is an array of pointers not an array of 8-bit data.变量数组维度必须是第一个,而不是最后一个,这是一个指针数组而不是 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();
}

}

test.py:测试.py:

Assuming cv2.imread() returns an np.array of the same type and shape as the declared ndpointer type, you would just pass it to the function directly.假设cv2.imread()返回与声明的np.array类型具有相同类型和形状的ndpointer ,您只需将其直接传递给 function。

from ctypes import *
import numpy as np
import numpy.ctypeslib as npct

lib = CDLL('./test')

class OBJ(Structure):
    _fields_ = []

ARRAY = npct.ndpointer(dtype=np.uint8,shape=(3,3,3))

lib.CreateObj.argtypes = c_int,
lib.CreateObj.restype = POINTER(OBJ)
lib.DoSomething.argtypes = POINTER(OBJ),ARRAY
lib.DoSomething.restype = c_int

arr = np.arange(27,dtype=np.uint8).reshape((3,3,3))
obj = lib.CreateObj(5)
result = lib.DoSomething(obj,arr)
print(f'result = {result}')
print(arr)

Output: Output:

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]]]

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM