如何将2d数组从Python传递到C?

我正在尝试使用ctypes将2d数组从Python传递到C。 数组dtype是uint16。 我编写了一个简单的代码只是为了了解其工作原理:

C:

#include <stdint.h>

__declspec(dllexport) uint16_t Test(uint16_t **arr)
{
     return (arr[5][5]);
}

Python:

import numpy as np
from ctypes import cdll
import ctypes
from numpy.ctypeslib import ndpointer

_p = ndpointer(dtype=np.uint16,ndim=2,shape=(10,10),flags='C')
mydll = cdll.Loadlibrary("mydll.dll")
_func = mydll.Test
_func.argtypes = [_p]
_func.restypes = ctypes.c_uint16

data = np.empty([10,10],dtype=np.uint16)
data[5,5] = 5
print(_func(data))

我收到OSError:访问冲突读取为0xFFFFFFFFFFFFFFFFFFFFFFFFF 我在做什么错以及如何解决?

ck19911018 回答:如何将2d数组从Python传递到C?

列出[SciPy.Docs]: C-Types Foreign Function Interface (numpy.ctypeslib)(和[Python 3.Docs]: ctypes - A foreign function library for Python以防万一)。

这与[SO]: Calling C function in Python through ctypes,but function returns incorrect value (@CristiFati's answer)完全一样(重复),只是碰巧也感染了 NumPy
换句话说,您具有 未定义行为 ,因为 argtypes 必须是 CTypes 类型(不是 NumPy )。

下面是您代码的修改版本,可以正常工作。

dll00.c

#include <stdint.h>

#if defined(_WIN32)
#  define DLL00_EXPORT_API __declspec(dllexport)
#else
#  define DLL00_EXPORT_API
#endif


#if defined(__cplusplus)
extern "C" {
#endif

DLL00_EXPORT_API uint16_t dll00Func00(uint16_t **ppArr);

#if defined(__cplusplus)
}
#endif


uint16_t dll00Func00(uint16_t **ppArr) {
    return ppArr[5][5];
}

code00.py

#!/usr/bin/env python3

import sys
import ctypes as ct
import numpy as np


DLL_NAME = "./dll00.dll"


def main():
    UI16Ptr = ct.POINTER(ct.c_uint16)
    UI16PtrPtr = ct.POINTER(UI16Ptr)

    dll00 = ct.CDLL(DLL_NAME)
    dll00Func00 = dll00.dll00Func00
    dll00Func00.argtypes = [UI16PtrPtr]
    dll00Func00.restype = ct.c_uint16


    dim0 = 10
    dim1 = 10
    np_arr_2d = np.empty([dim0,dim1],dtype=np.uint16)

    np_arr_2d[5][5] = 5
    print(np_arr_2d)

    # The "magic" happens in the following (3) lines of code
    ct_arr = np.ctypeslib.as_ctypes(np_arr_2d)
    UI16PtrArr = UI16Ptr * ct_arr._length_
    ct_ptr = ct.cast(UI16PtrArr(*(ct.cast(row,UI16Ptr) for row in ct_arr)),UI16PtrPtr)
    res = dll00Func00(ct_ptr)

    print("\n{0:s} returned: {1:d}".format(dll00Func00.__name__,res))


if __name__ == "__main__":
    print("Python {0:s} {1:d}bit on {2:s}\n".format(" ".join(item.strip() for item in sys.version.split("\n")),64 if sys.maxsize > 0x100000000 else 32,sys.platform))
    print("NumPy: {0:s}\n".format(np.version.version))
    main()
    print("\nDone.")

输出

[cfati@CFATI-5510-0:e:\Work\Dev\StackOverflow\q058727931]> sopr.bat
*** Set shorter prompt to better fit when pasted in StackOverflow (or other) pages ***

[prompt]> "c:\Install\x86\Microsoft\Visual Studio Community\2017\VC\Auxiliary\Build\vcvarsall.bat" x64
**********************************************************************
** Visual Studio 2017 Developer Command Prompt v15.9.17
** Copyright (c) 2017 Microsoft Corporation
**********************************************************************
[vcvarsall.bat] Environment initialized for: 'x64'

[prompt]> dir /b
code00.py
dll00.c

[prompt]> cl /nologo /DDLL dll00.c  /link /NOLOGO /DLL /OUT:dll00.dll
dll00.c
   Creating library dll00.lib and object dll00.exp

[prompt]> dir /b
code00.py
dll00.c
dll00.dll
dll00.exp
dll00.lib
dll00.obj

[prompt]> "e:\Work\Dev\VEnvs\py_064_03.07.03_test0\Scripts\python.exe" code00.py
Python 3.7.3 (v3.7.3:ef4ec6ed12,Mar 25 2019,22:22:05) [MSC v.1916 64 bit (AMD64)] 64bit on win32

NumPy: 1.16.2

[[19760  5277   632     0 32464  5280   632     0   111   114]
 [  107    92    68   101   118    92    86    69   110   118]
 [  115    92   112   121    95    48    54    52    95    48]
 [   51    46    48    55    46    48    51    95   116   101]
 [  115   116    48    92   108   105    98    92   115   105]
 [  116   101    45   112    97     5   107    97   103   101]
 [  115    92   110   117   109   112   121    92   116   101]
 [  115   116   105   110   103    92    95   112   114   105]
 [  118    97   116   101    92   110   111   115   101   116]
 [  101   115   116   101   114    46   112   121     0     0]]

dll00Func00 returned: 5

Done.

有关所有这些时髦转换的说明,请参见[SO]: C++ & Python: Pass and return a 2D double pointer array from python to c++ (@CristiFati's answer)(以及引用的[SO]: Problems with passing and getting arrays for a C function using ctypes (@CristiFati's answer))。

本文链接:https://www.f2er.com/3153135.html

大家都在问