Python ctypes 和 void const 指针
Python ctypes and void const pointers
我有一个 uint8 的 numpy 数组,我想通过 SWIG 将其作为指向 C++ 库的 void const 指针传递。
我使用这个 python 代码:
print(arr.ctypes.data_as(ctypes.c_void_p))
display.GetImageDisplay().SetImage(arr.ctypes.data_as(ctypes.c_void_p),arr.shape[0],arr.shape[1],1,1)
display.GetImageDisplay().Update()
要调用 ImageDisplay class 的 SetImage 方法,在 mvIMPACT aquire 库中:
void SetImage ( const void * pData,
int width,
int height,
int bitsPerPixel,
int pitch
)
我收到以下错误:
c_void_p(193598576)
Traceback (most recent call last):
File ".\mvIMPACT test.py", line 137, in <module>
display.GetImageDisplay().SetImage(arr.ctypes.data_as(ctypes.c_void_p),arr.shape[0],arr.shape[1],1,1)
File "C:\Program Files (x86)\Python37-32\lib\site-packages\mvIMPACT\acquire.py", line 7101, in SetImage
def SetImage(self, *args): return lib_mvIMPACT_acquire.ImageDisplay_SetImage(self, *args)
TypeError: in method 'ImageDisplay_SetImage', argument 2 of type 'void const *'
我认为pData的类型不对。我检查了 SWIG 包装器,我很确定我正在调用正确的函数,并且第一个类型匹配
SWIGINTERN PyObject *_wrap_ImageDisplay_SetImage__SWIG_0(PyObject *SWIGUNUSEDPARM(self), int nobjs, PyObject **swig_obj) {
PyObject *resultobj = 0; mvIMPACT::acquire::display::ImageDisplay *arg1 = (mvIMPACT::acquire::display::ImageDisplay *) 0 ;
void *arg2 = (void *) 0 ; int arg3 ; int arg4 ; int arg5 ; int arg6 ; void *argp1 = 0 ; int res1 = 0 ; int res2 ; int val3 ;
int ecode3 = 0 ; int val4 ; int ecode4 = 0 ; int val5 ; int ecode5 = 0 ; int val6 ; int ecode6 = 0 ;
if ((nobjs < 6) || (nobjs > 6)) SWIG_fail;
res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_mvIMPACT__acquire__display__ImageDisplay, 0 | 0 );
if (!SWIG_IsOK(res1)) {
SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "ImageDisplay_SetImage" "', argument " "1"" of type '" "mvIMPACT::acquire::display::ImageDisplay *""'"); }
arg1 = reinterpret_cast< mvIMPACT::acquire::display::ImageDisplay * >(argp1);
res2 = SWIG_ConvertPtr(swig_obj[1],SWIG_as_voidptrptr(&arg2), 0, 0); if (!SWIG_IsOK(res2)) {
SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "ImageDisplay_SetImage" "', argument " "2"" of type '" "void const *""'"); }
ecode3 = SWIG_AsVal_int(swig_obj[2], &val3); if (!SWIG_IsOK(ecode3)) {
SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "ImageDisplay_SetImage" "', argument " "3"" of type '" "int""'"); }
arg3 = static_cast< int >(val3); ecode4 = SWIG_AsVal_int(swig_obj[3], &val4); if (!SWIG_IsOK(ecode4)) {
SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "ImageDisplay_SetImage" "', argument " "4"" of type '" "int""'"); }
arg4 = static_cast< int >(val4); ecode5 = SWIG_AsVal_int(swig_obj[4], &val5); if (!SWIG_IsOK(ecode5)) {
SWIG_exception_fail(SWIG_ArgError(ecode5), "in method '" "ImageDisplay_SetImage" "', argument " "5"" of type '" "int""'"); }
arg5 = static_cast< int >(val5); ecode6 = SWIG_AsVal_int(swig_obj[5], &val6); if (!SWIG_IsOK(ecode6)) {
SWIG_exception_fail(SWIG_ArgError(ecode6), "in method '" "ImageDisplay_SetImage" "', argument " "6"" of type '" "int""'"); }
arg6 = static_cast< int >(val6); { try { { SWIG_PYTHON_THREAD_BEGIN_ALLOW;
(arg1)->SetImage((void const *)arg2,arg3,arg4,arg5,arg6); SWIG_PYTHON_THREAD_END_ALLOW; } }
catch(const mvIMPACT::acquire::ImpactAcquireException &e) { handleImpactAcquireException(e); SWIG_fail; }
catch(const std::exception &e) { SWIG_SetErrorMsg(PyExc_RuntimeError, e.what()); SWIG_fail; } catch(...) {
SWIG_SetErrorMsg(PyExc_RuntimeError, "unknown C++ exception"); SWIG_fail; } } resultobj = SWIG_Py_Void();
return resultobj; fail: return NULL; }
- 我 运行 遇到问题是因为我的指针不是常量吗?
- 我可以用 ctypes 创建一个常量指针吗?
- 我需要用另一个库复制我的 numpy 数组吗?
我知道一旦我 return 形成该调用,C++ 代码就不会使用数组。
我做了一个小例子来说明为什么不能将 ctypes.c_void_p
与用 SWIG 包装的函数一起使用,并提供了两个替代解决方案。
该示例是针对 C 库给出的 - 对于 C++,您需要找到第一部分的错位名称。
test.h
#pragma once
void SetImage(const void* pData,
int width,
int height,
int hitsPerPixel,
int pitch);
test.c
#include "test.h"
#include <stdio.h>
void SetImage(const void* pData,
int width,
int height,
int hitsPerPixel,
int pitch) {
double* _pData = (double*)pData;
printf("%f\n",_pData[0]);
}
编译
swig3.0 -python -includeall -Wall test.i
gcc -shared -o _example.so test.c test_wrap.c -Wall -Wextra -fPIC -I/usr/include/python2.7/ -DSWIGRUNTIME=extern
在Python中,您可以进行以下操作
import ctypes
import example
import numpy as np
arr = np.ones(10,dtype=np.float64)
arg = arr.ctypes.data_as(ctypes.c_void_p)
# Using the C functions
libexample = ctypes.cdll.LoadLibrary("_example.so")
libexample.SetImage(arg, 0,0,0,0)
n = 20
a = example.doubleArray(n)
a[0] = 37.0
# Using the SWIG wrapping
example.SetImage(a,0,0,0,0)
我有一个 uint8 的 numpy 数组,我想通过 SWIG 将其作为指向 C++ 库的 void const 指针传递。
我使用这个 python 代码:
print(arr.ctypes.data_as(ctypes.c_void_p))
display.GetImageDisplay().SetImage(arr.ctypes.data_as(ctypes.c_void_p),arr.shape[0],arr.shape[1],1,1)
display.GetImageDisplay().Update()
要调用 ImageDisplay class 的 SetImage 方法,在 mvIMPACT aquire 库中:
void SetImage ( const void * pData,
int width,
int height,
int bitsPerPixel,
int pitch
)
我收到以下错误:
c_void_p(193598576)
Traceback (most recent call last):
File ".\mvIMPACT test.py", line 137, in <module>
display.GetImageDisplay().SetImage(arr.ctypes.data_as(ctypes.c_void_p),arr.shape[0],arr.shape[1],1,1)
File "C:\Program Files (x86)\Python37-32\lib\site-packages\mvIMPACT\acquire.py", line 7101, in SetImage
def SetImage(self, *args): return lib_mvIMPACT_acquire.ImageDisplay_SetImage(self, *args)
TypeError: in method 'ImageDisplay_SetImage', argument 2 of type 'void const *'
我认为pData的类型不对。我检查了 SWIG 包装器,我很确定我正在调用正确的函数,并且第一个类型匹配
SWIGINTERN PyObject *_wrap_ImageDisplay_SetImage__SWIG_0(PyObject *SWIGUNUSEDPARM(self), int nobjs, PyObject **swig_obj) {
PyObject *resultobj = 0; mvIMPACT::acquire::display::ImageDisplay *arg1 = (mvIMPACT::acquire::display::ImageDisplay *) 0 ;
void *arg2 = (void *) 0 ; int arg3 ; int arg4 ; int arg5 ; int arg6 ; void *argp1 = 0 ; int res1 = 0 ; int res2 ; int val3 ;
int ecode3 = 0 ; int val4 ; int ecode4 = 0 ; int val5 ; int ecode5 = 0 ; int val6 ; int ecode6 = 0 ;
if ((nobjs < 6) || (nobjs > 6)) SWIG_fail;
res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_mvIMPACT__acquire__display__ImageDisplay, 0 | 0 );
if (!SWIG_IsOK(res1)) {
SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "ImageDisplay_SetImage" "', argument " "1"" of type '" "mvIMPACT::acquire::display::ImageDisplay *""'"); }
arg1 = reinterpret_cast< mvIMPACT::acquire::display::ImageDisplay * >(argp1);
res2 = SWIG_ConvertPtr(swig_obj[1],SWIG_as_voidptrptr(&arg2), 0, 0); if (!SWIG_IsOK(res2)) {
SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "ImageDisplay_SetImage" "', argument " "2"" of type '" "void const *""'"); }
ecode3 = SWIG_AsVal_int(swig_obj[2], &val3); if (!SWIG_IsOK(ecode3)) {
SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "ImageDisplay_SetImage" "', argument " "3"" of type '" "int""'"); }
arg3 = static_cast< int >(val3); ecode4 = SWIG_AsVal_int(swig_obj[3], &val4); if (!SWIG_IsOK(ecode4)) {
SWIG_exception_fail(SWIG_ArgError(ecode4), "in method '" "ImageDisplay_SetImage" "', argument " "4"" of type '" "int""'"); }
arg4 = static_cast< int >(val4); ecode5 = SWIG_AsVal_int(swig_obj[4], &val5); if (!SWIG_IsOK(ecode5)) {
SWIG_exception_fail(SWIG_ArgError(ecode5), "in method '" "ImageDisplay_SetImage" "', argument " "5"" of type '" "int""'"); }
arg5 = static_cast< int >(val5); ecode6 = SWIG_AsVal_int(swig_obj[5], &val6); if (!SWIG_IsOK(ecode6)) {
SWIG_exception_fail(SWIG_ArgError(ecode6), "in method '" "ImageDisplay_SetImage" "', argument " "6"" of type '" "int""'"); }
arg6 = static_cast< int >(val6); { try { { SWIG_PYTHON_THREAD_BEGIN_ALLOW;
(arg1)->SetImage((void const *)arg2,arg3,arg4,arg5,arg6); SWIG_PYTHON_THREAD_END_ALLOW; } }
catch(const mvIMPACT::acquire::ImpactAcquireException &e) { handleImpactAcquireException(e); SWIG_fail; }
catch(const std::exception &e) { SWIG_SetErrorMsg(PyExc_RuntimeError, e.what()); SWIG_fail; } catch(...) {
SWIG_SetErrorMsg(PyExc_RuntimeError, "unknown C++ exception"); SWIG_fail; } } resultobj = SWIG_Py_Void();
return resultobj; fail: return NULL; }
- 我 运行 遇到问题是因为我的指针不是常量吗?
- 我可以用 ctypes 创建一个常量指针吗?
- 我需要用另一个库复制我的 numpy 数组吗? 我知道一旦我 return 形成该调用,C++ 代码就不会使用数组。
我做了一个小例子来说明为什么不能将 ctypes.c_void_p
与用 SWIG 包装的函数一起使用,并提供了两个替代解决方案。
该示例是针对 C 库给出的 - 对于 C++,您需要找到第一部分的错位名称。
test.h
#pragma once
void SetImage(const void* pData,
int width,
int height,
int hitsPerPixel,
int pitch);
test.c
#include "test.h"
#include <stdio.h>
void SetImage(const void* pData,
int width,
int height,
int hitsPerPixel,
int pitch) {
double* _pData = (double*)pData;
printf("%f\n",_pData[0]);
}
编译
swig3.0 -python -includeall -Wall test.i
gcc -shared -o _example.so test.c test_wrap.c -Wall -Wextra -fPIC -I/usr/include/python2.7/ -DSWIGRUNTIME=extern
在Python中,您可以进行以下操作
import ctypes
import example
import numpy as np
arr = np.ones(10,dtype=np.float64)
arg = arr.ctypes.data_as(ctypes.c_void_p)
# Using the C functions
libexample = ctypes.cdll.LoadLibrary("_example.so")
libexample.SetImage(arg, 0,0,0,0)
n = 20
a = example.doubleArray(n)
a[0] = 37.0
# Using the SWIG wrapping
example.SetImage(a,0,0,0,0)