我想在 C 函式中復制一個 2D numpy 陣列(矩陣),然后在 python 中取回它(然后利用 C 的速度優勢在 C 中對其進行一些計算)。因此,我需要 C 函式matrix_copy
回傳一個二維陣列(或者,我猜是指向它的指標)。我嘗試使用以下代碼,但得到以下輸出(可以看到陣列的第二維丟失了)。
matrix_in.shape:
(300, 200)
matrix_out.shape:
(300,)
我怎樣才能更改代碼(我猜是matrix_copy.c
添加一些指標魔術),以便我可以獲得matrix_in
in的精確副本matrix_out
?
這是main.py
腳本:
from ctypes import c_void_p, c_double, c_int, cdll
from numpy.ctypeslib import ndpointer
import numpy as np
import pdb
n = 300
m = 200
matrix_in = np.random.randn(n, m)
lib = cdll.LoadLibrary("matrix_copy.so")
matrix_copy = lib.matrix_copy
matrix_copy.restype = ndpointer(dtype=c_double,
shape=(n,))
matrix_out = matrix_copy(c_void_p(matrix_in.ctypes.data),
c_int(n),
c_int(m))
print("matrix_in.shape:")
print(matrix_in.shape)
print("matrix_out.shape:")
print(matrix_out.shape)
這是matrix_copy.c
腳本:
#include <stdlib.h>
#include <stdio.h>
double * matrix_copy(const double * matrix_in, int n, int m){
double * matrix_out = (double *)malloc(sizeof(double) * (n*m));
int index = 0;
for(int i=0; i< n; i ){
for(int j=0; j<m; j ){
matrix_out[i j] = matrix_in[i j];
//matrix_out[i][j] = matrix_in[i][j];
// some heavy computations not yet implemented
}
}
return matrix_out;
}
我用命令編譯
cc -fPIC -shared -o matrix_copy.so matrix_copy.c
作為旁注,為什么符號matrix_out[i][j] = matrix_in[i][j];
會在編譯時給我一個錯誤?
matrix_copy.c:10:26: error: subscripted value is not an array, pointer, or vector
matrix_out[i][j] = matrix_in[i][j];
~~~~~~~~~~~~~^~
matrix_copy.c:10:44: error: subscripted value is not an array, pointer, or vector
matrix_out[i][j] = matrix_in[i][j];
uj5u.com熱心網友回復:
第二個維度是“丟失”的,因為您在 的命名shape
引數中明確省略了它ndpointer
。改變:
matrix_copy.restype = ndpointer(dtype=c_double, shape=(n,))
至
matrix_copy.restype = ndpointer(dtype=c_double, shape=(n,m), flags='C')
其中flags='C'
還指出,回傳的資料以row major order連續存盤。
關于matrix_out[i][j] = matrix_in[i][j];
拋出錯誤,請考慮matrix_in
型別為const double *
. matrix_in[i]
會產生一個型別的值const double
- 你如何進一步索引這個值(即,用[j]
)?
如果要模擬通過單個指標訪問二維陣列,則必須手動計算偏移量。matrix_out[i j]
還不夠,因為您必須考慮每個子陣列的跨度:
matrix_out[i * m j] = matrix_in[i * m j];
請注意,在 C 中,size_t
在處理記憶體大小或陣列長度時,通常首選使用的型別。
matrix_copy.c
,簡化:
#include <stdlib.h>
double *matrix_copy(const double *matrix_in, size_t n, size_t m)
{
double *matrix_out = malloc(sizeof *matrix_out * n * m);
for (size_t i = 0; i < n; i )
for (size_t j = 0; j < m; j )
matrix_out[i * m j] = matrix_in[i * m j];
return matrix_out;
}
matrix.py
,更明確的型別:
from ctypes import c_void_p, c_double, c_size_t, cdll, POINTER
from numpy.ctypeslib import ndpointer
import numpy as np
c_double_p = POINTER(c_double)
n = 300
m = 200
matrix_in = np.random.randn(n, m).astype(c_double)
lib = cdll.LoadLibrary("matrix_copy.so")
matrix_copy = lib.matrix_copy
matrix_copy.argtypes = c_double_p, c_size_t, c_size_t
matrix_copy.restype = ndpointer(
dtype=c_double,
shape=(n,m),
flags='C')
matrix_out = matrix_copy(
matrix_in.ctypes.data_as(c_double_p),
c_size_t(n),
c_size_t(m))
print("matrix_in.shape:", matrix_in.shape)
print("matrix_out.shape:", matrix_out.shape)
print("in == out", matrix_in == matrix_out)
uj5u.com熱心網友回復:
傳入的資料可能是單個記憶體塊。您需要創建子結構。
在我的 C 代碼中,我必須對通過 swig 傳入的資料(塊)執行以下操作:
void divide2DDoubleArray(double * &block, double ** &subblockdividers, int noofsubblocks, int subblocksize){
/* The starting address of a block of doubles is used to generate
* pointers to subblocks.
*
* block: memory containing the original block of data
* subblockdividers: array of subblock addresses
* noofsubblocks: specify the number of subblocks produced
* subblocksize: specify the size of the subblocks produced
*
* Design by contract: application should make sure the memory
* in block is allocated and initialized properly.
*/
// Build 2D matrix for cols
subblockdividers=new double *[noofsubblocks];
subblockdividers[0]= block;
for (int i=1; i<noofsubblocks; i) {
subblockdividers[i] = &subblockdividers[i-1][subblocksize];
}
}
現在 subblockdividers 中回傳的指標可以按照您想要的方式使用。
完成后不要忘記釋放 subblockdividers。(注意:可能需要調整才能將其編譯為 C 代碼)
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/508401.html
上一篇:測驗c中某些短語的有效性