强化学习笔记(4) 使用SWIG和CMake给C++库创建一个Python接口wrapping C++ to python

一些废话

在实际应用中笔者被一个问题困扰了很久,就是自己的C++写的环境没办法用上python搭建的深度神经网络和一些强化学习的库(实际是C++搞深度学习实在是恶心,python实在是太香了)。在实际工程中其实也存在这样的问题,因为实际上很多应用都是用C/C++写的。尤其是一些游戏,各种物理引擎渲染都是用C++写的,而且C++接口用起来比较优雅。但是这些软件的应用都没有python接口,而且python官方提供的python语言本身的C++接口Python.h也确实用起来很麻烦,笔者尝试过使用,用了一阵后发现,实在是太恶心人(工期快到)了就打算另辟蹊径。于是某一天在使用一个C++库的时候意外发现了这个SWIG。幸运的是,SWIG支持很多编译器,比如说gcc, Ninjia,Cmake等. 最后在python环境下可以顺利使用C++写好的库。

环境准备

system: Ubuntu 20.04
cmake: 3.16.3
gcc: 10.3
swig: 4.0.2
Vscode: 能用就行

初始文件夹结构

在这里插入图片描述

具体步骤

上面结构中example.cpp, .h, .i和CMakeLists为需要写的文件。try.py是用来测试的。
下面我将example三个文件内容贴出来

  1. example.cpp
#include "example.h"

void try_class::class_func(int a)
{
    this->param-=a;
}


// calculate factorial
ll int fact(ll int n)
{
  return n+1;
}
  
//find mod
int my_mod(int n, int m)
{
  return(n % m);
}

  1. example.h
#define ll long long

class try_class
{
  public:
  int param=20;
  void class_func(int a);
};

ll int fact(ll int n);
int my_mod(int n, int m);
  1. example.i
%module example

%{
#include "example.h"
%}
%include "example.h"
  1. CMakeLists.txt
set(CMAKE_CXX_STANDARD 20)

#寻找PYTHONHOME的环境变量
find_package (Python3 COMPONENTS Interpreter Development)
include_directories(${Python3_INCLUDE_DIRS})
link_libraries(${Python3_LIBRARIES})

#指定你的.cxx等文件的目录
include_directories(${PROJECT_SOURCE_DIR}/src)

#寻找安装好的swig,其实就是去电脑中找你安装好的Swig环境,所以我们需要提前安装环境。
find_package(SWIG REQUIRED)
include(${SWIG_USE_FILE})

#Python文件输出目录 -outdir
set(CMAKE_SWIG_OUTDIR ${CMAKE_CURRENT_BINARY_DIR}/python)

#指定一个输出目录名,用于放置生成的源文件。例如输出的examplePTYHON_wrap.cxx文件等的位置
set(SWIG_OUTFILE_DIR ${CMAKE_CURRENT_BINARY_DIR}/cpp)#use "SWIG" with “CMake”  wrapping CPP to python

#注意这一步必须要加上,要不然不能编译c++,只能编译c
set_property(SOURCE src/example.i PROPERTY CPLUSPLUS ON)

#开始生成
swig_add_library(example 
                LANGUAGE python 
                SOURCES src/example.i src/example.cpp)

swig相关的函数在VScode中是不会高亮的,但是你可以在Cmake官网上找到用法和各个变量的说明。
然后就是到build文件夹下去编译工程

cd build
cmake ..
make

然后你的工程文件夹结构就变成了下面这样,咱们需要用到的文件并不多。一个是build/python/example.py另一个是build/_example.so。将这两个全部复制出来放到你的测试文件try.py同一个文件夹下就可以直接在try.py中使用了。

├── build
│   ├── CMakeCache.txt
│   ├── CMakeFiles
│   │   ├── 3.16.3
│   │   │   ├── CMakeCCompiler.cmake
│   │   │   ├── CMakeCXXCompiler.cmake
│   │   │   ├── CMakeDetermineCompilerABI_C.bin
│   │   │   ├── CMakeDetermineCompilerABI_CXX.bin
│   │   │   ├── CMakeSystem.cmake
│   │   │   ├── CompilerIdC
│   │   │   │   ├── a.out
│   │   │   │   ├── CMakeCCompilerId.c
│   │   │   │   └── tmp
│   │   │   └── CompilerIdCXX
│   │   │       ├── a.out
│   │   │       ├── CMakeCXXCompilerId.cpp
│   │   │       └── tmp
│   │   ├── cmake.check_cache
│   │   ├── cmake_directory_clean.cmake
│   │   ├── CMakeDirectoryInformation.cmake
│   │   ├── CMakeOutput.log
│   │   ├── CMakeRuleHashes.txt
│   │   ├── CMakeTmp
│   │   ├── _example.dir
│   │   │   ├── build.make
│   │   │   ├── cmake_clean.cmake
│   │   │   ├── cpp
│   │   │   │   └── examplePYTHON_wrap.cxx.o
│   │   │   ├── CXX.includecache
│   │   │   ├── DependInfo.cmake
│   │   │   ├── depend.internal
│   │   │   ├── depend.make
│   │   │   ├── examplePYTHON.stamp
│   │   │   ├── flags.make
│   │   │   ├── link.txt
│   │   │   ├── progress.make
│   │   │   └── src
│   │   │       └── example.cpp.o
│   │   ├── example_swig_compilation.dir
│   │   │   ├── build.make
│   │   │   ├── cmake_clean.cmake
│   │   │   ├── CXX.includecache
│   │   │   ├── DependInfo.cmake
│   │   │   ├── depend.internal
│   │   │   ├── depend.make
│   │   │   └── progress.make
│   │   ├── Makefile2
│   │   ├── Makefile.cmake
│   │   ├── progress.marks
│   │   └── TargetDirectories.txt
│   ├── cmake_install.cmake
│   ├── compile_commands.json
│   ├── cpp
│   │   └── examplePYTHON_wrap.cxx
│   ├── _example.so
│   ├── Makefile
│   └── python
│       └── example.py
├── CMakeLists.txt
├── src
│   ├── example.cpp
│   ├── example.h
│   └── example.i
└── try.py

15 directories, 49 files

try.py

import example

c1=example.try_class()
print(c1.param)
c1.class_func(2)
print(c1.param)

可以看到输出

> python try.py 
20
18
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值