天天看點

Windows平台搭建Swig環境示例,并且解決python無法傳回double類型的問題

1. Windows下安裝Swig

詳情參考 https://blog.csdn.net/aganliang/article/details/91129379

2. 建立test.cpp檔案

#include "test.h"

int addReturnInt(int a, int b)
{
	return a + b;
}

void addPointerDouble(double& a, double& b, double& res)
{
	res = a + b;
}
           

建立test.h檔案

#ifndef TEST_H
#define TEST_H

int addReturnInt(int a, int b);

#ifdef SWIG
%apply double& INPUT{ double& a }
%apply double& INPUT{ double& b }
%apply double& INOUT{ double& res }
#endif
void addPointerDouble(double & a, double & b, double & res);

#endif
           

建立test.i檔案

%module TestSwig
%{
#include "test.h"
%}
%include "test.h"
           

将這三個建立的檔案放入一個檔案夾中

3. 打開cmd指令行 cd進剛剛建立的檔案夾内

執行swig指令

swig -c++ -python  test.i

執行完畢後,會在目前目錄下生成一個名為test_wrap.cxx的檔案以及TestSwig.py檔案

4. 打開VS,建立一個C++空項目(控制台)

在菜單欄(正上方)設定為release x86, 将cxx檔案,h檔案,cpp檔案添加進項目中

5. python環境配置:

  • 配置改為Release x86
  • 配置屬性->正常->Windows SDK版本修改為【10.0.18362.0】或【最新安裝版本】
  • 配置屬性->正常->配置類型修改為【動态庫(.dll)】
  • 配置屬性->進階->目标檔案擴充名修改為【.pyd】
  • 配置屬性->C/C++->正常->附加包含目錄->添加【D:\anconda\envs\py36\include】
  • 配置屬性->VC++目錄->庫目錄->添加【D:\anconda\envs\py36\libs】(即為python36.lib所在路徑)
  • 配置屬性->連接配接器->輸入->附加依賴項->添加【python36.lib】

6. VS編譯項目,點選生成選項,會在配置的輸出目錄中生成TestSwig.pyd檔案。生成完畢之後将此檔案重命名為_TestSwig.pyd(原因:與剛剛swig生成的py檔案重名了,不利于調用)

7. 将pyd檔案與生成的py檔案放在同一個目錄下

執行測試代碼:

import TestSwig

a = 1
b = 2
res = TestSwig.addReturnInt(a, b)
print('原生C++ int 傳回:', type(res), res)

print('-------------------------')

a1 = 1.0
a2 = 2.0
res = 0.0

# 這裡的res是通過swig編譯腳本裡的INOUT關鍵字傳回
res = TestSwig.addPointerDouble(a1, a2, res) 的
print('原生C++ double 引用傳回:', type(res), res)

           

執行結果:

原生C++ int 傳回: <class 'int'> 3

-------------------------

原生C++ double 引用傳回: <class 'float'> 3.0

至此,python就可以調用c++封裝的函數了

總結:

test.h中的swig宏是解決python類型中沒有double類型傳回的關鍵

#ifdef SWIG
%apply double& INPUT{ double& a }
%apply double& INPUT{ double& b }
%apply double& INOUT{ double& res }
#endif

其中:% 與apply不能分離(這個巨坑,别問我怎麼知道的)
參數與函數保持一緻,如果函數入參為int這種非引用、指針類型的,可以不寫入SWIG宏内
INPUT代表輸入輸出,編譯後的python得出結果需要傳回(因為python沒有顯式的使用指針)
OUTOUT代表輸出,隻能在python内return出結果
INPUT代表輸入,隻能通過python指派給C++函數參數
           

更新:使用c++ class風格的swig封裝

頭檔案test.h:

#ifndef TEST_H
#define TEST_H

class ClassTest
{
public:
	ClassTest();
	~ClassTest();
	int addReturnIntCpp(int a, int b);

	#ifdef SWIG
	%apply double& INPUT{ double& a }
	%apply double& INPUT{ double& b }
	%apply double& INOUT{ double& res }
	#endif
	void addPointerDoubleCpp(double& a, double& b, double& res);
};
#endif
           

類檔案test.cpp:

#include "test.h"

ClassTest::ClassTest(){}
ClassTest::~ClassTest() {}

int ClassTest::addReturnIntCpp(int a, int b)
{
	return a + b;
}

void ClassTest::addPointerDoubleCpp(double& a, double& b, double& res)
{
	res = a + b;
}
           

i檔案同上,編譯方式同上。