posts - 20,comments - 15,trackbacks - 0

python调用c dll api


关键字: python dll调用 np类型转换 double


关于python调用dll的文章有很多, 本篇主要描述对double数组传参的实现, 本人还没有发现类似的文章, 因此书写本文档加以说明。

本文实现主要参考《用python进行科学计算》一书, 因此对环境有要求, 环境需要安装python(x,y), 该软件可以很好的支持numpy库,
否则用sf上下载的numpy安装包直接在python里安装貌似装了不生效, 也就是import numpy失败

下面简单讲下实现过程

1. 制作dll, 假设dll中有如下的导出函数, dll名为smooth
// @param: n   数组长度
// @param: x   [input/output] 一维数组
// @param: y   [input/output]
// @param: weights   [input]  可为0
// @param: s   [input/output] 单值,返回新的x,y长度
int smooth(int n, double* x, double* y, double* weights, double* s);


2. 加载dll
import numpy as np
from ctypes import *

dll = np.ctypeslib.load_library('smooth', '.')


3. 执行函数
c里的double是64位的, 因此简单的传参会是32位的, 比如用下面的实现就会有这样的问题
smooth = dll.smooth
#[Warning:下面是一个错误的演示]
#描述参数类型
smooth.argtypes = [c_int, POINTER(c_double), POINTER(c_double), POINTER(c_double), POINTER(c_double)]
#返回值类型
smooth.restype = c_int
x = [3.2, 3.9, 5.4, 5.9]
x = np.array(x)
y = np.array(x)
w = np.array(0)
s = np.array(10)
smooth(len(x), x.ctypes.data_as(POINTER(c_double)), y.ctypes.data_as(POINTER(c_double)), w.ctypes.data_as(POINTER(c_double)), s.ctypes.data_as(POINTER(c_double)) )

调用后python没有报错, 但不能得到正确的结果, 进入vc附加python进程, 在函数头加上断点, 查看参数内存, 可看出其是以int*方式传入的
要让python以真正的64位double*传入可使用下面的实现
#正确的调用
smooth.argtypes = [
    c_int,
    np.ctypeslib.ndpointer(dtype=np.float64, ndim=1, flags="C_CONTIGUOUS"), #一维数组,且内存连续的
    np.ctypeslib.ndpointer(dtype=np.float64, ndim=1, flags="C_CONTIGUOUS"),
    np.ctypeslib.ndpointer(dtype=np.float64),
    np.ctypeslib.ndpointer(dtype=np.float64)
]
smooth.restype = c_int
m = [3.2, 3.9, 5.4, 5.9]
x = np.arange(4, dtype=np.float64)
y = np.arange(4, dtype=np.float64)
w = np.cast["float64"](0)
s = np.cast["float64"](10)
for i in range(0, len(m)):
 x[i] = m[i]
 y[i] = m[i]
smooth(len(x), x, y, w, s)

题外话: python的参数基本可以看为指针, 类似引用等操作都可以轻松完成

本人对numpy不是很熟, 可能对于np的参数初始化有更好的方式, 此处就算抛砖引玉吧,

 

 


 

posted on 2013-08-27 11:34 wangkang 阅读(2870) 评论(0)  编辑 收藏 引用

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理