C ++和Python:将2D双指针数组从python传递并返回到c ++ [英] C++ & Python: Pass and return a 2D double pointer array from python to c++
问题描述
我想将2D数组从Python传递到C ++函数,然后将相同类型,相同尺寸的数组返回给Python.我知道这个问题已经被问过几次了,但是我找不到与我问题相关的答案.对于我的问题,我必须使用双指针数组,并使函数返回双指针数组(如许多示例所示,不是 void
).
I want to pass a 2D array from Python to a C++ function and then return an array of the same type, same dimensions, to Python. I am aware this question has already been asked several times, but I haven't been able to find a relevant answer to my question. For my problem, I must use a double pointer array and have the function returning a double pointer array (not void
as many examples show).
我的C ++函数是:
#include <stdio.h>
#include <stdlib.h>
extern "C" double** dot(double **a, int m, int n){
double **arr = (double **)malloc(m * sizeof(double *));
for (int i=0; i<m; i++)
arr[i] = (double*)malloc(n * sizeof(double));
for (int i=0; i < m; i++){
for (int j=0; j < n; j++){
arr[i][j] = a[i][j];
}
}
return arr;
}
目前,我已经使用了 Ctypes
.我知道我可以使用 Swig
界面,但是由于我不太了解它,我宁愿避免使用它.但是,我仍然愿意接受任何建议.我必须使用 Swig
的问题是,如果我没有记错的话,我必须使用 Typemap
来分解指针结构,这是一个部分,我不太了解.
For the moment, I have used Ctypes
. I know I could use the Swig
interface but I would prefer avoiding it given that I don't know it very well. However, I am still open to any suggestion. My problem if I had to use Swig
is that, if I'm not mistaking, I would have to use a Typemap
in order to decompose the pointer structure, and it's a part I don't understand very well.
我目前在Python中尝试过的是:
What I have tried for the moment in Python is:
import ctypes as c
import numpy as np
ty_ = np.ctypeslib._ctype_ndarray(c.POINTER(c.POINTER(c.c_double)), (3,3))
x = np.arange(9.).reshape(3,3)
_dll = ctypes.CDLL('./double_2D.so')
_foobar = _dll.dot
_foobar.argtype = type(y)
_foobar.restype = type(y)
d = _foobar(y, 3, 3) #I would like d to be a nice matrix like x
我也尝试过
c.cast(_foobar(y,3,3), c.POINTER(c.POINTER(c.c_double)))
但以上示例均无效.因此,关于在 Swig
中定义 argtype
或 restype
或 Typemap
的代码段的任何建议都是很大的帮助.
But none of the examples above work. So therefore, any suggestion for defining the argtype
or restype
, or a snippet for Typemap
in Swig
would be of great help.
推荐答案
列出思想夫妇:
- "双指针数组"具有误导性:
- 没有数组
- "双指针"可能表示双精度指针或双精度指针指向某物(包括 double )
- "double pointer array" is misleading:
- There is no array
- "double pointer" might mean either pointer to double or pointer to pointer to something (including double)
无论如何,这是一个简单的演示示例.
Anyway, here's a simple example for demo purposes.
dll00.c :
#include <stdio.h> #include <stdlib.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 double **init(double **ppMat, int m, int n); DLL00_EXPORT_API int cleanup(double **ppMat, int m); #if defined(__cplusplus) } #endif DLL00_EXPORT_API double **init(double **ppMat, int m, int n) { const double factor = 7.0; printf("\n----- FROM C: Multiplying input matrix by: %.3f\n", factor); double **ret = malloc(m * sizeof(double*)); for (int i = 0; i < m; i++) { ret[i] = malloc(n * sizeof(double)); for (int j = 0; j < n; j++) { ret[i][j] = ppMat[i][j] * factor; } } return ret; } DLL00_EXPORT_API int cleanup(double **ppMat, int m) { int ret = 0; if (ppMat) { printf("\n----- FROM C: free\n"); for (int i = 0; i < m; i++) { free(ppMat[i]); ret++; ppMat[i] = NULL; } free(ppMat); } return ++ret; }
code00.py :
#!/usr/bin/env python3 import sys import ctypes as ct from pprint import pprint as pp DLL_NAME = "./dll00.dll" def ptr2d_to_mat(ptr, rows, cols): return tuple(tuple(ptr[i][j] for j in range(cols)) for i in range(rows)) def main(): dll00 = ct.CDLL(DLL_NAME) init = dll00.init cleanup = dll00.cleanup rows = 4 cols = 6 DblPtr = ct.POINTER(ct.c_double) DblPtrPtr = ct.POINTER(DblPtr) init.argtypes = [DblPtrPtr, ct.c_int, ct.c_int] init.restype = DblPtrPtr cleanup.argtypes = [DblPtrPtr, ct.c_int] cleanup.restype = ct.c_int DblPtrArr = DblPtr * rows DblArr = ct.c_double * cols DblArrArr = DblArr * rows first_value = 6 in_mat = tuple(tuple(range(cols * i + first_value, cols * (i + 1) + first_value)) for i in range(rows)) print("Input matrix:") pp(in_mat) in_arr = DblArrArr(*in_mat) in_ptr = ct.cast(DblPtrArr(*(ct.cast(row, DblPtr) for row in in_arr)), DblPtrPtr) # Cast each row and the final array to (corresponding) pointers out_ptr = init(in_ptr, rows, cols) out_mat = ptr2d_to_mat(out_ptr, rows, cols) cleanup(out_ptr, rows) print("\nOutput matrix:") pp(out_mat) 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)) main() print("\nDone.")
输出:
[cfati@CFATI-5510-0:e:\Work\Dev\StackOverflow\q058226790]> 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.16 ** 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 Input matrix: ((6, 7, 8, 9, 10, 11), (12, 13, 14, 15, 16, 17), (18, 19, 20, 21, 22, 23), (24, 25, 26, 27, 28, 29)) ----- FROM C: Multiplying input matrix by: 7.000 ----- FROM C: free Output matrix: ((42.0, 49.0, 56.0, 63.0, 70.0, 77.0), (84.0, 91.0, 98.0, 105.0, 112.0, 119.0), (126.0, 133.0, 140.0, 147.0, 154.0, 161.0), (168.0, 175.0, 182.0, 189.0, 196.0, 203.0)) Done.
You can also take a look at [SO]: Problems with passing and getting arrays for a C function using ctypes (@CristiFati's answer), which is very similar (almost identical, I'd say) to this one.
这篇关于C ++和Python:将2D双指针数组从python传递并返回到c ++的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!