python - 什么 ctypes 参数类型用于可变修改的多维数组

在 python 中使用 ctypes 我可以使用指向其第一个元素的指针将数组自由地传递给 C 函数,因为数组衰减为指向其第一个元素的指针C。所以对于 C 函数签名

void insert_sort(int A[], size_t length);

我可以实现以下 python 包装器。

import ctypes
from typing import List, Callable

def wrap_function(lib: ctypes.CDLL, name: str, restype: object, argtypes: List[object]) -> Callable:
    """Simplify wrapping ctypes functions"""
    func = lib.__getattr__(name)
    func.restype = restype
    func.argtypes = argtypes
    return func


lib = ctypes.CDLL("path/to/library.so")
insert_sort = wrap_function(lib, 'insert_sort', None, [ctypes.POINTER(ctypes.c_int), ctypes.c_size_t])

但是 C 还允许一个人拥有数组的数组以及更多可变大小的数组数组。例如,下面的 C 函数签名演示了这一点。

void matrix_multiply(size_t n, int A[n][n], int B[n][n], int C[n][n]);

如何包装这个函数?为了整理我的问题,下面的空白处是什么?

matrix_multiply = wrap_function(lib, 'matrix_multiply', None, [...What goes here...])

如果知道数组的大小,我们可以简单地写

matrix_multiply = wrap_function(lib, 'matrix_multiply', None, [
    ctypes.c_size_t, ((ctypes.c_int * 4)*4), ((ctypes.c_int * 4)*4), ((ctypes.c_int * 4)*4)
])

对于大小为 4 的数组。但是当这个数字未知时我们能做什么呢?

最佳答案

此答案基于对 ABI 的逆向工程。我把这个测试程序编译成汇编...

#include <stddef.h>
extern void matrix_multiply(size_t n, int A[n][n], int B[n][n], int C[n][n]);

extern int X[64][64];
extern int Y[64][64];
extern int Z[64][64];

void test(void)
{
  matrix_multiply(64, X, Y, Z);
}

...在 x86_64-linux 上使用 GCC 9,我得到了这个汇编语言:

test:
    leaq    Z(%rip), %rcx
    leaq    Y(%rip), %rdx
    leaq    X(%rip), %rsi
    movl    $64, %edi
    jmp matrix_multiply@PLT

基于此我得出结论,可变修改的数组参数作为指向其第一个元素的指针传递,因此 matrix_multiply 的适当 ctypes 声明是

c_int_p = ctypes.POINTER(ctypes.c_int)
matrix_multiply = wrap_function(lib, 'matrix_multiply', None, [
    ctypes.c_size_t, c_int_p, c_int_p, c_int_p
])

采用 NumPy 数组和/或内存 View 作为练习的包装器。

https://stackoverflow.com/questions/62489384/

相关文章:

c# - 在延续中使用一个对象,确保它在你需要它之​​前不会被释放

javascript - 如何使 React 组件更可重用?

swift - Xcode 预览不适用于通用 View

r - 探索澳大利亚人口普查数据的最佳方式?

r - 理解 R 中的 Pretty()

python - Numpy-recarray,C#结构化数据

c# - SSIS - 文件存在性检查未正确控制包任务流

C# System.TypeLoadException : Could not load type

react-native - 如何使用 RNFetchBlob.fetch 和 react-nati

c# - 如何为本地 toast 通知自行注册独立桌面 C# WPF 应用程序(作为 exe 分发)