ctypes and Python 3:我的项目一个严重的回调函数问题
Ctypes and Python 3: A serious callback function problem for my project
下面显示的 C 代码通过处理包含 7 x 3 整数值的矩阵作为输入来生成包含 7x7 浮点值的输出。 (实际上,输入矩阵大小可能是7000 x 3,列数是固定的,但行数可以改变)
input
1 0 0
2 1 0
3 1 2
4 0 0
5 4 0
6 4 5
7 5 6
cfun.c
#include<stdio.h>
#include<stdlib.h>
float** nrm_matrix(int **A, int R) {
float** ped=(float**)malloc(R*sizeof(float*));
for (int i = 0; i < R; i++){
ped[i]=(float*)malloc(sizeof(float)*R);
}
for(int i=0; i<R; i++){
for(int j=0;j<R;j++){
ped[i][j]=A[0][0]+0.8;
ped[j][i]=A[6][0]+0.3;
}
}
return ped;
free(ped);
}
出于某些令人信服的原因,我使用一对指针 float** nrm_matrix(int **A, int R) 创建了一个函数。此函数在 C 环境中运行良好,并如前所述提供以下输出:
output
7.30 7.30 7.30 7.30 7.30 7.30 7.30
1.80 7.30 7.30 7.30 7.30 7.30 7.30
1.80 1.80 7.30 7.30 7.30 7.30 7.30
1.80 1.80 1.80 7.30 7.30 7.30 7.30
1.80 1.80 1.80 1.80 7.30 7.30 7.30
1.80 1.80 1.80 1.80 1.80 7.30 7.30
1.80 1.80 1.80 1.80 1.80 1.80 7.30
我想从 python 调用这个函数 3. 我编译了 C 代码并准备了 test.py 文件,如下所示:
gcc -o nrm.so --shared -fPIC cfun.c
test.py
import numpy as np
import ctypes
from ctypes import *
dll = ctypes.CDLL("./nrm.so")
nrmfunc = dll.nrm_matrix
nrmfunc.argtypes = POINTER(POINTER(c_int)), c_int
nrmfunc.restype = ctypes.c_float
x=np.matrix([[1, 0, 0], #<------------input file as a matrix
[2, 1, 0],
[3, 1, 2],
[4, 0, 0],
[5, 4, 0],
[6, 4, 5],
[7, 5, 6]])
rows = 7
y=nrmfunc(x, rows)
print(y)
Traceback (most recent call last):
File "C:\Users\Casper\Desktop\sorulacak\test.py", line 29, in <module>
y=nrmfunc(x, rows)
ctypes.ArgumentError: argument 1: <class 'TypeError'>: expected LP_LP_c_long instance instead of matrix
当我 运行 这段代码时,我得到了这个错误。我已经尝试整整五天了,但我无法解决问题。我是编码的新手。请帮我。我该如何解决这个问题???
numpy
数组是 two-dimensional 数组,而不是指针数组。进行以下更改:
test.c
#include <stdio.h>
#include <stdlib.h>
#ifdef _WIN32
# define API __declspec(dllexport)
#else
# define API
#endif
API float** nrm_matrix(int *A, int R) { // Change from int **A to int *A
float** ped = (float**)malloc(R * sizeof(float*));
for (int i = 0; i < R; i++){
ped[i] = (float*)malloc(sizeof(float) * R);
}
for(int i = 0; i < R; i++) {
for(int j = 0; j < R; j++) {
ped[i][j] = A[0*3+0] + 0.8; // row/column calculation col * 3 + row
ped[j][i] = A[6*3+0] + 0.3; // in this case
}
}
return ped;
}
test.py
import numpy as np
from ctypes import *
dll = CDLL("./test")
nrmfunc = dll.nrm_matrix
# expect a numpy array of type int and 2 dimensions.
nrmfunc.argtypes = np.ctypeslib.ndpointer(dtype=int, ndim=2), c_int
# expect a float** as output
nrmfunc.restype = POINTER(POINTER(c_float))
x = np.matrix([[1, 0, 0], #<------------input file as a matrix
[2, 1, 0],
[3, 1, 2],
[4, 0, 0],
[5, 4, 0],
[6, 4, 5],
[7, 5, 6]])
rows = 7
y = nrmfunc(x, rows)
# a float** doesn't return information about size.
# slice y to the known size to iterate float*.
# slice row to get the floats in the row.
for row in y[:rows]:
print(row[:7])
输出:
[7.300000190734863, 7.300000190734863, 7.300000190734863, 7.300000190734863, 7.300000190734863, 7.300000190734863, 7.300000190734863]
[1.7999999523162842, 7.300000190734863, 7.300000190734863, 7.300000190734863, 7.300000190734863, 7.300000190734863, 7.300000190734863]
[1.7999999523162842, 1.7999999523162842, 7.300000190734863, 7.300000190734863, 7.300000190734863, 7.300000190734863, 7.300000190734863]
[1.7999999523162842, 1.7999999523162842, 1.7999999523162842, 7.300000190734863, 7.300000190734863, 7.300000190734863, 7.300000190734863]
[1.7999999523162842, 1.7999999523162842, 1.7999999523162842, 1.7999999523162842, 7.300000190734863, 7.300000190734863, 7.300000190734863]
[1.7999999523162842, 1.7999999523162842, 1.7999999523162842, 1.7999999523162842, 1.7999999523162842, 7.300000190734863, 7.300000190734863]
[1.7999999523162842, 1.7999999523162842, 1.7999999523162842, 1.7999999523162842, 1.7999999523162842, 1.7999999523162842, 7.300000190734863]
下面显示的 C 代码通过处理包含 7 x 3 整数值的矩阵作为输入来生成包含 7x7 浮点值的输出。 (实际上,输入矩阵大小可能是7000 x 3,列数是固定的,但行数可以改变)
input
1 0 0
2 1 0
3 1 2
4 0 0
5 4 0
6 4 5
7 5 6
cfun.c
#include<stdio.h>
#include<stdlib.h>
float** nrm_matrix(int **A, int R) {
float** ped=(float**)malloc(R*sizeof(float*));
for (int i = 0; i < R; i++){
ped[i]=(float*)malloc(sizeof(float)*R);
}
for(int i=0; i<R; i++){
for(int j=0;j<R;j++){
ped[i][j]=A[0][0]+0.8;
ped[j][i]=A[6][0]+0.3;
}
}
return ped;
free(ped);
}
出于某些令人信服的原因,我使用一对指针 float** nrm_matrix(int **A, int R) 创建了一个函数。此函数在 C 环境中运行良好,并如前所述提供以下输出:
output
7.30 7.30 7.30 7.30 7.30 7.30 7.30
1.80 7.30 7.30 7.30 7.30 7.30 7.30
1.80 1.80 7.30 7.30 7.30 7.30 7.30
1.80 1.80 1.80 7.30 7.30 7.30 7.30
1.80 1.80 1.80 1.80 7.30 7.30 7.30
1.80 1.80 1.80 1.80 1.80 7.30 7.30
1.80 1.80 1.80 1.80 1.80 1.80 7.30
我想从 python 调用这个函数 3. 我编译了 C 代码并准备了 test.py 文件,如下所示:
gcc -o nrm.so --shared -fPIC cfun.c
test.py
import numpy as np
import ctypes
from ctypes import *
dll = ctypes.CDLL("./nrm.so")
nrmfunc = dll.nrm_matrix
nrmfunc.argtypes = POINTER(POINTER(c_int)), c_int
nrmfunc.restype = ctypes.c_float
x=np.matrix([[1, 0, 0], #<------------input file as a matrix
[2, 1, 0],
[3, 1, 2],
[4, 0, 0],
[5, 4, 0],
[6, 4, 5],
[7, 5, 6]])
rows = 7
y=nrmfunc(x, rows)
print(y)
Traceback (most recent call last):
File "C:\Users\Casper\Desktop\sorulacak\test.py", line 29, in <module>
y=nrmfunc(x, rows)
ctypes.ArgumentError: argument 1: <class 'TypeError'>: expected LP_LP_c_long instance instead of matrix
当我 运行 这段代码时,我得到了这个错误。我已经尝试整整五天了,但我无法解决问题。我是编码的新手。请帮我。我该如何解决这个问题???
numpy
数组是 two-dimensional 数组,而不是指针数组。进行以下更改:
test.c
#include <stdio.h>
#include <stdlib.h>
#ifdef _WIN32
# define API __declspec(dllexport)
#else
# define API
#endif
API float** nrm_matrix(int *A, int R) { // Change from int **A to int *A
float** ped = (float**)malloc(R * sizeof(float*));
for (int i = 0; i < R; i++){
ped[i] = (float*)malloc(sizeof(float) * R);
}
for(int i = 0; i < R; i++) {
for(int j = 0; j < R; j++) {
ped[i][j] = A[0*3+0] + 0.8; // row/column calculation col * 3 + row
ped[j][i] = A[6*3+0] + 0.3; // in this case
}
}
return ped;
}
test.py
import numpy as np
from ctypes import *
dll = CDLL("./test")
nrmfunc = dll.nrm_matrix
# expect a numpy array of type int and 2 dimensions.
nrmfunc.argtypes = np.ctypeslib.ndpointer(dtype=int, ndim=2), c_int
# expect a float** as output
nrmfunc.restype = POINTER(POINTER(c_float))
x = np.matrix([[1, 0, 0], #<------------input file as a matrix
[2, 1, 0],
[3, 1, 2],
[4, 0, 0],
[5, 4, 0],
[6, 4, 5],
[7, 5, 6]])
rows = 7
y = nrmfunc(x, rows)
# a float** doesn't return information about size.
# slice y to the known size to iterate float*.
# slice row to get the floats in the row.
for row in y[:rows]:
print(row[:7])
输出:
[7.300000190734863, 7.300000190734863, 7.300000190734863, 7.300000190734863, 7.300000190734863, 7.300000190734863, 7.300000190734863]
[1.7999999523162842, 7.300000190734863, 7.300000190734863, 7.300000190734863, 7.300000190734863, 7.300000190734863, 7.300000190734863]
[1.7999999523162842, 1.7999999523162842, 7.300000190734863, 7.300000190734863, 7.300000190734863, 7.300000190734863, 7.300000190734863]
[1.7999999523162842, 1.7999999523162842, 1.7999999523162842, 7.300000190734863, 7.300000190734863, 7.300000190734863, 7.300000190734863]
[1.7999999523162842, 1.7999999523162842, 1.7999999523162842, 1.7999999523162842, 7.300000190734863, 7.300000190734863, 7.300000190734863]
[1.7999999523162842, 1.7999999523162842, 1.7999999523162842, 1.7999999523162842, 1.7999999523162842, 7.300000190734863, 7.300000190734863]
[1.7999999523162842, 1.7999999523162842, 1.7999999523162842, 1.7999999523162842, 1.7999999523162842, 1.7999999523162842, 7.300000190734863]