SWIG 打包C++數組供python調用 tcy

1.1.carrays.i        
用途:   
    該模塊定義將普通C指針包裝爲數組的宏;不提供任何安全性;
    僅提供用於建立,銷燬和修改原始C數組數據內容的功能
1.2.%array_functions(type, name)  
    用途:建立四個函數,供你建立銷燬輔值及讀數組元素
    函數:
        type *new_name(int nelements)  //建立新動態數組分配內存
        type *delete_name(type *ary)  //銷燬數組
        type name_getitem(type *ary, int index)  //讀數組元素
        void name_setitem(type *ary, int index, type value)  //設置設置元素
            
    說明:type但是任何類型;name不該該與接口文件中有重名

    示例:        
    void print_array(double x[6]) {  
        int i;  
        for (i = 0; i < 6; i++) { printf("[%d] = %g\n", i, x[i]);  }  
    }  

    包裝:        
          %module example  
            
          %include "carrays.i"  
          %array_functions(double, doubleArray);  
            
          void print_array(double x[10]);  
          
    python測試:         
        a = new_doubleArray(10)               # Create an array  
        for i in range(0, 10):  
          doubleArray_setitem(a, i, 2 * i)     # Set a value  
          
        print_array(a)                                  # Pass to C  
        delete_doubleArray(a)                    # Destroy array
1.3.%array_class(type, name)  
        
用途:將指針包裝爲類;在基於類接口內包裝*類型指針;常與代理類結合使用    
注意:類型限制爲簡單類型如int或float   
結構:
    struct name {  
        name(int nelements);                      // Create an array  
        ~name();                                           // Delete array  
        type getitem(int index);                    // Return item  
        void setitem(int index, type value);  // Set item  
        type *cast();                                      // Cast to original type  
        static name *frompointer(type *);     // Create class wrapper from  existing pointer  
    };  

實例:
    %module example  
    %include "carrays.i"  
    %array_class(double, doubleArray);  

    void print_array(double x[10]);  
    
    python操做:        

    import example  
    
    c = example.doubleArray(10)  # Create double[10]  
    for i in range(0, 10):  
      c[i] = 2 * i                               # Assign values  
    example.print_array(c)             # Pass to C
1.4.注意:
    %array_functions,%array_class宏不會將C數組封裝在特殊數據結構或代理中
    沒有邊界檢查或任何形式安全性。如須要應該考慮使用特殊數組對象而不是裸指針

    %array_functions,%array_class不該與char或char *類型一塊兒使用
    SWIG對這些類型默認做爲字符串處理
2.實例:

實例1:數組-自定義輔助函數
#pragma once
//1.1.example.h

void add(float *rst_arr, const float *arr, int rst_size, int size);

//1.2.Example.cpp
#include "Example.h"

void add(float *rst_arr, const float *arr, int rst_size, int size)
{
 float n = 0;
 
 for (int i = 0;i < rst_size; i++)
 {
  if (i < size)
   rst_arr[i] = arr[i] + 100;
  else
   rst_arr[i] = n + 100;

  n += 1;
 }
}
//1.3.1.SWIG接口文件Example.i
//自定義數組輔助函數

%module Example//定義模塊名

%{
#include "Example.h"
%}

#include "Example.h"
using namespace std;

%inline%{

static float *new_floatArray(size_t nelements) { 
    return (new float[nelements]());
}

static void delete_floatArray(float *ary){
 delete[] ary;
}

static float floatArray_getitem(float *ary, size_t index) {
    return ary[index];
  }
static void floatArray_setitem(float *ary, size_t index, float value) {
    ary[index] = value;
}

%}

void add(float *rst_arr,const float *arr, int rst_size, int size);
//1.3.2.SWIG接口文件Example.i
//用carray.i

%module Example//定義模塊名
%include "carrays.i"
%array_functions(float, floatArray);

%{
#include "Example.h"
%}

#include "Example.h"
using namespace std;

%}

void add(float *rst_arr,const float *arr, int rst_size, int size);
//1.3.3.SWIG接口文件Example.i
//自定義數組輔助類(推薦)自動釋放指針

%module Example//定義模塊名

%{
#include "Example.h"
%}

#include "Example.h"
using namespace std;

%inline%{

class FloatArrClass
{
private:
 size_t size;
 float *p_float;

public:
 size_t getSize(){return size;}
 float *getFloatPointer(){return p_float;}

 float *new_floatArray(size_t nelements) {
  return (new float[nelements]());
 }

 void delete_floatArray(float *ary) {
  delete[] ary;
 }

 float floatArray_getitem(float *ary, size_t index) {
  return ary[index];
 }
 void floatArray_setitem(float *ary, size_t index, float value) {
  ary[index] = value;
 }
    
    void floatArray_setitem(float *ary, size_t index, float value) {
  ary[index] = value;
 }//swig不支持設置arr[]下標重載
    
 FloatArrClass() { size = 0; }
 FloatArrClass(size_t n) { size = n; p_float = new_floatArray(n); }
 FloatArrClass(const FloatArrClass &o) { size = o.size; p_float = o.p_float; }
 ~FloatArrClass() {
  if (p_float != NULL) { delete_floatArray(p_float); p_float = NULL; }
 }
};  

%}

void add(float *rst_arr,const float *arr, int rst_size, int size);
//1.4.python測試程序:
# !/usr/bin/env python
# -*- coding: utf-8 -*-

# from Swig.Camera import add,HalconClass
import numpy as np
import sys,os,shutil

def copyfile(b=True):
    if b==False:return
    pypath=r'C:\Users\Administrator\Desktop\Fastener\Swig'
    cpath=r'C:\Users\Administrator\Desktop\ProjectSwigWin\x64\Release'
    filename=r'Example'
    cfile_py=cpath+'\\'+filename+'.py'
    cfile_pyd=cpath+r'\ProjectSwigWin.pyd'

    pyfile_py=pypath+'\\'+filename+'.py'
    pyfile_pyd=pypath+r'\_'+filename+'.pyd'

    print(cfile_py)
    if os.path.isfile(cfile_py):
        shutil.copyfile(cfile_py,pyfile_py)
    else:
        print('not camera.py',cfile_py)
        return

    if os.path.isfile(cfile_pyd):
        shutil.copyfile(cfile_pyd,pyfile_pyd)
    else:
        print('not camera.pyd')
        return

copyfile()
from Swig import Example  as obj

#數組測試:
def test_Add_C_PulsPulse(obj,obj1,obj2,rst_arr,arr,n=6):
    obj1=obj1 if obj1 else obj
    obj2 = obj2 if obj2 else obj
    for i in range(n):           #初始化數組
        obj1.floatArray_setitem(rst_arr, i, 0)
        obj2.floatArray_setitem(arr, i, i)

    obj.add(rst_arr,arr, n, n)#rst_arr=arr+100

    print('test arr:')
    for i in range(6):             #顯示數組元素
        print("[%6.2f %6.2f]" % (obj.floatArray_getitem(rst_arr, i), obj.floatArray_getitem(arr, i)))

# 自定義函數或用carray.i
n=6
rst_arr = obj.new_floatArray(n)
arr = obj.new_floatArray(n)

test_Add_C_PulsPulse(obj,None,None,rst_arr,arr,n)
#
obj.delete_floatArray(rst_arr)
obj.delete_floatArray(arr)

#類操做數組:
a1=obj.FloatArrClass(6)
a2=obj.FloatArrClass(6)

size1=a1.getSize()
size2=a2.getSize()

rst_arr=a1.getFloatPointer()
arr=a2.getFloatPointer()

test_Add_C_PulsPulse(obj,a1,a2,rst_arr,arr,n)

============================================================================
https://blog.csdn.net/qianshuyuankk/article/details/103051774