利用swig 编写c/c++扩展到Python的接口( 数组通过numpy传递)

swig+python+numpy:c/c++扩展Python的接口(特别是“数组”的传递)

简要说明

本人因为项目需要,做c、c++到matlab、python的接口,matlab的文档比较齐全,官方也有些例子,照着例子画瓢,多少也没那么难,暂时不太想做其相关的接口举例(官方mex 指令生成对应的文件或者库)。在做python的接口遇到一些问题,特别是数组或者指针的问题,网上找寻半天,还好找到名为“numpy.i”文件的线索,简单做了个关于数组处理的例子,这里记录下,方便其他人少走坑;网上说“swig”做接口方便,强大,于是就‘swig’来做设计对应python接口的,当然也有一些其它的方法,当热也要准备写好“setup.py”文件(不管什么方法,这一步无论如何不可少),下面尽可能讲清使用,不做深入研究。

运行环境说明

简单说明下自己运行环境:win10,python3.6在的anaconda3里面配置的一个虚拟环境(spyder是挺好用的IDE,方便调试python代码,anaconda界面下安装很方便的),swig是在官网下载的windows( swigwin-4.0.1 :http://www.swig.org/download.html)版本,解压swigwin-4.0.1就可以用了,不过注意配置好swig和python的环境变量(swig.exe…,方便在命令窗口输指令),以上就够了;当然自己准备的c/c++代码可以通过Notepad、Sublime Text 等等上编辑,或者直接在Visual Studio上提前试着运行,看个人了。

所需准备的文件说明

  1. 比如要建立一个名为“npPtrC”的模块,python中导入“import npPtrC”,然后运行该模块下的c/c++代码,这大概就是python的模块扩展吧。需要准备至少这些 “npPtrC.i,numpy.i(处理数组需要的),npPtrC.cpp,npPtrC.h,setup.py”文件;

  2. 自己可运行的代码是放到 npPtrC.cpp,npPtrC.h这个里面的,对python可见的接口最好都放到一个头文件下,比如放到npPtrC.h里面。npPtrC.i就是swig要处理的“接口文件”,里面会包含numpy.i文件,numpy.i文件的说明可以看numpy的官方文档:numpy.i: a SWIG Interface File for NumPy,里面有句话“The numpy.i file is currently located in the tools/swig sub-directory under the numpy installation directory. ”,github的“numpy/tools/swig/”这个路径能找到对应文件numpy.i。至于setup.py文件怎么写,可以网上查找,里面有很多选项的,个人后面会进一步尝试的。

  3. 命令:1) swig -c++ -python .\npPtrC.i;2)python .\setup.py build_ext --inplace。就这两行命令,swig处理成功后,会编译出“npPtrC.py和npPtrC_wrap.cxx”文件,python 处理后会生成_npPtrC.cp36-win_amd64.pyd,这个大概就是库了,windows上是这样的,linux上貌似是.so了。这就完成了,然后写个test.py或者直接用命令行去测试就行了。

例子相关代码和内容

1.npPtrC.cpp文件:

#include "npPtrC.h"

double pyCArrayInteraction::sqrtSumInputArrays1D(float * inputA1, int D1)
{
	double r = 0.0;

	int i = 0;
	for ( i = 0; i < D1; i++)
	{
		r += inputA1[i] * inputA1[i];
		inputA1[i] = 123.456+i;//test
	}


	return sqrt(r);
}

double pyCArrayInteraction::sqrtSumInputArrays2D(float * inputA2, int D1, int D2)
{
	int i=0, j=0;
	double r=0;
	float * temPtr = NULL;
	printf("\r\n");
	for ( i = 0; i < D1; i++)
	{
		temPtr = inputA2 + i * D2;
		printf("[%d][0]--%f ",i,*temPtr);
		for (j = 0; j < D2; j++)
		{
			r += temPtr[j] * temPtr[j];
		}
		*temPtr = 2.3456;//test
	}
	printf("\r\n");

	return sqrt(r);
}

double pyCArrayInteraction::sqrtSumInputArrays3D(float * inputA3, int D1, int D2, int D3)
{
	int i = 0, j = 0, k = 0;
	double r = 0;
	float * temPtr = NULL;
	printf("\r\n");

	for ( i = 0; i < D1; i++)
	{
		for( j = 0; j < D2; j++)
		{
			temPtr = temPtr = inputA3 + (i * D2+j)*D3;
			printf("[%d][%d][0]--%f ", i, j, *temPtr);
			for (k = 0; k < D3; k++)
			{
				r += temPtr[k] * temPtr[k];
			}
			*temPtr = 0.633456;//test
		}
	}
	printf("\r\n");


	return sqrt(r);
}
  1. npPtrC.h 文件:
#pragma once
#include <math.h>
#include <iostream>

class pyCArrayInteraction
{
public:
	double sqrtSumInputArrays1D(float* inputA1,int D1);
	double sqrtSumInputArrays2D(float* inputA2, int D1, int D2);
	double sqrtSumInputArrays3D(float* inputA3, int D1, int D2, int D3);

private:

};
  1. npPtrC.i文件:
/* File : npPtrC.i */
%module npPtrC
%{
#define SWIG_FILE_WITH_INIT
#include "npPtrC.h"
%}
%include "numpy.i"
%init %{
import_array();
%}

%apply (float* IN_ARRAY1,int DIM1) {(float* inputA1, int D1 )}
%apply (float* IN_ARRAY2,int DIM1,int DIM2) {(float* inputA2, int D1, int D2)}
%apply (float* IN_ARRAY3,int DIM1,int DIM2,int DIM3) {(float* inputA3,int D1,int D2, int D3)}

%include "npPtrC.h"
  1. setup.py文件:
#!/usr/bin/env python

"""
setup.py file for SWIG C++/Python example
"""
from distutils.core import setup, Extension
import numpy as np

example_module = Extension('_npPtrC',
    sources=['npPtrC.cpp', 'npPtrC_wrap.cxx',],
     include_dirs=[np.get_include()]
)
setup (
    name = 'good',
    version = '0.1',
    author = "yj",
    description = """abc""",
    ext_modules = [example_module],
    py_modules = ["Test"],
)
  1. test.py文件:
import numpy as np
#from ctypes import *
import npPtrC


#TEST BY YJ

npTest =npPtrC.pyCArrayInteraction()

arr_1 = np.array([0,1,2,3,4,5], dtype = np.float32)

arr_2 = np.arange(10,dtype = np.float32).reshape(2,5)

arr_3 = np.arange(2*3*7,dtype = np.float32).reshape(2,3,7)

print(npTest.sqrtSumInputArrays1D(arr_1))

print(npTest.sqrtSumInputArrays2D(arr_2))

print(npTest.sqrtSumInputArrays3D(arr_3))

print("arr_1:",arr_1,"\r\n")
print("arr_2:",arr_2,"\r\n")
print("arr_3:",arr_3,"\r\n")

print('...... job')
  1. python上运行的截图结果:

python打印结果

结语

大家相互帮助,现在知识很多,共享的人也很多,对那些提供帮助,整理分享的人表示敬意,由于个人能力有限,有不对的地方还请纠正。

  • 0
    点赞
  • 2
    收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
©️2022 CSDN 皮肤主题:大白 设计师:CSDN官方博客 返回首页
评论

打赏作者

meng_zhi_xiang

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值