簡體   English   中英

如何將二維數組從 Python 傳遞到 C?

[英]How to pass a 2d array from Python to C?

我正在嘗試使用 ctypes 將二維數組從 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:訪問沖突讀取 0xFFFFFFFFFFFFFFFFFFFFFFF 我做錯了什么,我該如何解決?

清單[SciPy.Docs]: C-Types Foreign Function Interface (numpy.ctypeslib) (和[Python 3.Docs]: ctypes - A foreign function library for ZA7F5F35426B6282171中的案例)

This is a exactly like [SO]: Calling C function in Python through ctypes, but function returns incorrect value (@CristiFati's answer) (a duplicate), it just happens to also involve NumPy .
換句話說,您有Undefined Behavior ,因為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];
}

代碼00.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.")

Output

 [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.

The explanation for all those funky conversions can be found at [SO]: C++ & Python: Pass and return a 2D double pointer array from python to c++ (@CristiFati's answer) (and the referenced [SO]: Problems with passing and getting arrays對於使用 ctypes 的 C function (@CristiFati 的回答)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM