使用 ctypes 调用带有指针参数的 C++ 函数

Posted

技术标签:

【中文标题】使用 ctypes 调用带有指针参数的 C++ 函数【英文标题】:Using ctypes to call C++ function with pointer args 【发布时间】:2019-01-01 15:48:18 【问题描述】:

一些背景知识(可能与问题没有直接关系):我需要执行一个已知稀疏度的高效矩阵乘法。 因为它是稀疏的,所以使用正常的矩阵乘法是一种浪费,而且因为它是一种已知的稀疏性,我可以用一种有效的方式来实现它,而不是使用稀疏库。

我已经用 C++ 实现了我的功能

void SparsePrecisionMult(double *Q, double *X, double *out, const int dim, const int markov, const int n);

这是“包装器”:

import ctypes
_SPMlib = ctypes.CDLL('./SparsePrecisionMult.so')
_SPMlib.SparsePrecisionMult.argtypes = (ctypes.POINTER(ctypes.c_double), ctypes.POINTER(ctypes.c_double), ctypes.POINTER(ctypes.c_double),
                                        ctypes.c_int, ctypes.c_int, ctypes.c_int)

def sparse_precision_mult(Q, X, out, markov_blanket_size):
    global _SPM
    m, d = X.shape
    _SPMlib.SparsePrecisionMult(Q.ctypes.data_as(ctypes.POINTER(ctypes.c_double)),
                                X.T.ctypes.data_as(ctypes.POINTER(ctypes.c_double)),
                                out.ctypes.data_as(ctypes.POINTER(ctypes.c_double)),
                                d, markov_blanket_size, m)

我就是这样称呼它的:

patch_size = 3
markov_blanket = 3

C = np.eye(9)
X = np.array(range(0, 27, 1)).reshape(3, 9)

out = np.zeros([3, 9])

sparse_precision_mult(C.astype(np.float64), X.astype(np.float64), out.astype(np.float64), 3)

print(out)

这个测试的结果应该是 out=X。 用 C 编写的这个测试的一个版本表现良好。 我出去=零。所以我的猜测是,不知何故,内存没有被共享和被复制。 我不想在我的 RAM 上重复数据(此函数将用于高维矩阵)。那我该如何解决呢?

谢谢。

【问题讨论】:

【参考方案1】:

astype 创建一个数组的副本。因此out.astype(np.float64) 参数给sparse_precision_mult 提供了一个副本,该副本被修改然后丢弃。原始out 未修改。

使用np.float64 类型创建out 并(如有必要)在函数调用后进行转换。

如果可能,您应该创建具有函数调用所需类型的所有参数,以避免被astype 复制。

astype 有一个参数 copy 可以设置为 False 以避免不必要的副本,但最好确保副本是/不需要而不是依赖它。

【讨论】:

以上是关于使用 ctypes 调用带有指针参数的 C++ 函数的主要内容,如果未能解决你的问题,请参考以下文章

带有指针参数的 C++ 函数

使用 ctypes 传递结构指针

没有为指向结构的指针调用 ctypes.Structure 子类的 ctypes __del__

C++函数指针与成员函数指针

Python ctypes:带有 LPCSTR [out] 参数的原型

指针函数参数损坏,堆栈损坏?