简体   繁体   English

Python ctypes和void const指针

[英]Python ctypes and void const pointers

I have an numpy array of uint8, that I would like to pass as a void const pointer to a C++ library through SWIG. 我有一个uint8的numpy数组,我想通过SWIG作为void const指针传递给C ++库。

I use this python code: 我使用以下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()

To call the SetImage method of the ImageDisplay class, in the mvIMPACT aquire library: 要在mvIMPACT获取库中调用ImageDisplay类的SetImage方法:

void SetImage   (   const void *    pData,
        int     width,
        int     height,
        int     bitsPerPixel,
        int     pitch 
    )   

I get the following error: 我收到以下错误:

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 *'

I think the type of pData is wrong. 我认为pData的类型是错误的。 I checked the SWIG wrapper, and I'm quite sure I'm calling the correct function, and the first type matches 我检查了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; }
  1. Am I running into issues because my pointer is not constant? 我的指针不是恒定的,是否遇到问题?
  2. Can I make a constant pointer with ctypes? 我可以用ctypes做一个常量指针吗?
  3. Do I need to make a copy of my numpy array with another library? 我是否需要使用另一个库复制numpy数组? I know that the C++ code is not using the array once I return form that call. 我知道一旦我从调用中返回C ++代码就不会使用数组。

I have made a small example demonstrating why you cannot use ctypes.c_void_p together with a function wrapped with SWIG and provided two alternative solutions. 我举了一个小例子,说明为什么不能将ctypes.c_void_p与SWIG包装的函数一起使用,并提供了两种替代解决方案。

The example is given for a C library - for C++ you need to find the mangled names for the first part. 该示例是针对C库提供的-对于C ++,您需要查找第一部分的错误名称。

test.h test.h

#pragma once

void SetImage(const void* pData,
              int width,
              int height,
              int hitsPerPixel,
              int pitch);

test.c 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]);
}

To compile 编译

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

In Python, you can do the following 在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)

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

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