gpt4 book ai didi

python - 如何将二维数组从 Python 传递到 C?

转载 作者:太空宇宙 更新时间:2023-11-03 23:36:45 56 4
gpt4 key购买 nike

我正在尝试使用 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: access violation reading 0xFFFFFFFFFFFFFFFFFFFFFFFF我做错了什么,我该如何解决?

最佳答案

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

这是一模一样的 [SO]: C function called from Python via ctypes 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 python

import ctypes as ct
import sys

import numpy as np


DLL_NAME = "./dll00.{:s}".format("dll" if sys.platform[:3].lower() == "win" else "so")


def main(*argv):
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 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 {:s} {:03d}bit on {: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))
rc = main(*sys.argv[1:])
print("\nDone.")
sys.exit(rc)

输出:

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

[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)] 064bit 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) )。

关于python - 如何将二维数组从 Python 传递到 C?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58727931/

56 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com