用swig封装c++代码给python使用

前面我们用swig封装了c++的代码给java使用:

如何用SWIG封装c++接口给java使用?-CSDN博客

 

但是由于我们的代码写的太好了,python用户也想用,我们需要将c++代码封装一下给python用户使用。

这种需求很常见吧。

现在AI动不动就是用python进行训练,但是有些需要提高运行速度的时候还是需要用C/C++进行编写。

python与c++进行交互的方式好像挺多的。

ctype,pybind11,但这里我们还是使用swig。

代码还是使用我们在java那里的例子。

让我们看看我们优秀的代码是怎么给python程序员带来震撼的。

apple.h

#ifndef __APPLE_H__
#define __APPLE_H__
 
 
enum class LogLevel {
    Trace  /// Most detailed output
    ,Debug
    ,Info
    ,Warn
    ,Error
    ,Fatal  /// Least detailed output
    ,Current  /// no-op, value indicates current level should be retained
};
 
 
class Apple
{
public:
    Apple();
    int GetColor(void);
    void SetColor(int color);
    
private:
    int m_nColor;
};
#endif 

apple.cpp

#include "apple.h"
 
Apple::Apple() : m_nColor(0)
{
}
 
void Apple::SetColor(int color)
{
    m_nColor = color;
}
 
int Apple::GetColor(void)
{
    return m_nColor;
}

我们在这两个文件里面定义了一个类Apple,给它添加了两个成员函数Setcolor和GetColor,是不是非常合理,一般的C++都是这么写的。

写swig接口文件  apple.i

%module demo
%{
/* Includes the header in the wrapper code */
#include "apple.h"
%}

/* Parse the header file to generate wrappers */
%include "apple.h"

用swig生成中间代码

swig -python -c++ apple.i

生成了 demo.py和 apple_wrap.cxx 两个文件

编译一下这个 cxx文件,生成 _demo.so

g++ -g -c apple.cpp   -o apple.o
g++ -fpic -shared apple_wrap.cxx  -o _demo.so  -I/usr/include/python3.8 apple.o

 用python调用一下试试。

main.py


import demo;

a = demo.Apple();
a.SetColor(2);
print(a.GetColor());


运行之

pp@dell:~/wrapper$ python3 main.py 
2

非常好!

我们来看一下swig给我们生成的中间文件都有什么内容。

 apple_wrap.cxx 的内容:

文件总共3804行,我们只看比较核心的部分,函数的实现。

SWIGINTERN PyObject *_wrap_Apple_SetColor(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
  PyObject *resultobj = 0;
  Apple *arg1 = (Apple *) 0 ;
  int arg2 ;
  void *argp1 = 0 ;
  int res1 = 0 ;
  int val2 ;
  int ecode2 = 0 ;
  PyObject *swig_obj[2] ;
  
  if (!SWIG_Python_UnpackTuple(args, "Apple_SetColor", 2, 2, swig_obj)) SWIG_fail;
  res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_Apple, 0 |  0 );
  if (!SWIG_IsOK(res1)) {
    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Apple_SetColor" "', argument " "1"" of type '" "Apple *""'"); 
  }
  arg1 = reinterpret_cast< Apple * >(argp1);
  ecode2 = SWIG_AsVal_int(swig_obj[1], &val2);
  if (!SWIG_IsOK(ecode2)) {
    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Apple_SetColor" "', argument " "2"" of type '" "int""'");
  } 
  arg2 = static_cast< int >(val2);
  (arg1)->SetColor(arg2);
  resultobj = SWIG_Py_Void();
  return resultobj;
fail:
  return NULL;
}


SWIGINTERN PyObject *Apple_swigregister(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
  PyObject *obj;
  if (!SWIG_Python_UnpackTuple(args, "swigregister", 1, 1, &obj)) return NULL;
  SWIG_TypeNewClientData(SWIGTYPE_p_Apple, SWIG_NewClientData(obj));
  return SWIG_Py_Void();
}

SWIGINTERN PyObject *Apple_swiginit(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
  return SWIG_Python_InitShadowInstance(args);
}

static PyMethodDef SwigMethods[] = {
	 { "SWIG_PyInstanceMethod_New", SWIG_PyInstanceMethod_New, METH_O, NULL},
	 { "new_Apple", _wrap_new_Apple, METH_NOARGS, NULL},
	 { "Apple_GetColor", _wrap_Apple_GetColor, METH_O, NULL},
	 { "Apple_SetColor", _wrap_Apple_SetColor, METH_VARARGS, NULL},
	 { "delete_Apple", _wrap_delete_Apple, METH_O, NULL},
	 { "Apple_swigregister", Apple_swigregister, METH_O, NULL},
	 { "Apple_swiginit", Apple_swiginit, METH_VARARGS, NULL},
	 { NULL, NULL, 0, NULL }
};

static PyMethodDef SwigMethods_proxydocs[] = {
	 { NULL, NULL, 0, NULL }
};

demo.py的内容就比较简单了,只有90行

基本上 就是一个封装和函数调用转发。

# This file was automatically generated by SWIG (http://www.swig.org).
# Version 4.0.1
#
# Do not make changes to this file unless you know what you are doing--modify
# the SWIG interface file instead.

from sys import version_info as _swig_python_version_info
if _swig_python_version_info < (2, 7, 0):
    raise RuntimeError("Python 2.7 or later required")

# Import the low-level C/C++ module
if __package__ or "." in __name__:
    from . import _demo
else:
    import _demo

try:
    import builtins as __builtin__
except ImportError:
    import __builtin__

def _swig_repr(self):
    try:
        strthis = "proxy of " + self.this.__repr__()
    except __builtin__.Exception:
        strthis = ""
    return "<%s.%s; %s >" % (self.__class__.__module__, self.__class__.__name__, strthis,)


def _swig_setattr_nondynamic_instance_variable(set):
    def set_instance_attr(self, name, value):
        if name == "thisown":
            self.this.own(value)
        elif name == "this":
            set(self, name, value)
        elif hasattr(self, name) and isinstance(getattr(type(self), name), property):
            set(self, name, value)
        else:
            raise AttributeError("You cannot add instance attributes to %s" % self)
    return set_instance_attr


def _swig_setattr_nondynamic_class_variable(set):
    def set_class_attr(cls, name, value):
        if hasattr(cls, name) and not isinstance(getattr(cls, name), property):
            set(cls, name, value)
        else:
            raise AttributeError("You cannot add class attributes to %s" % cls)
    return set_class_attr


def _swig_add_metaclass(metaclass):
    """Class decorator for adding a metaclass to a SWIG wrapped class - a slimmed down version of six.add_metaclass"""
    def wrapper(cls):
        return metaclass(cls.__name__, cls.__bases__, cls.__dict__.copy())
    return wrapper


class _SwigNonDynamicMeta(type):
    """Meta class to enforce nondynamic attributes (no new attributes) for a class"""
    __setattr__ = _swig_setattr_nondynamic_class_variable(type.__setattr__)


LogLevel_Trace = _demo.LogLevel_Trace
LogLevel_Debug = _demo.LogLevel_Debug
LogLevel_Info = _demo.LogLevel_Info
LogLevel_Warn = _demo.LogLevel_Warn
LogLevel_Error = _demo.LogLevel_Error
LogLevel_Fatal = _demo.LogLevel_Fatal
LogLevel_Current = _demo.LogLevel_Current
class Apple(object):
    thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag")
    __repr__ = _swig_repr

    def __init__(self):
        _demo.Apple_swiginit(self, _demo.new_Apple())

    def GetColor(self):
        return _demo.Apple_GetColor(self)

    def SetColor(self, color):
        return _demo.Apple_SetColor(self, color)
    __swig_destroy__ = _demo.delete_Apple

# Register Apple in _demo:
_demo.Apple_swigregister(Apple)



可以说,速度是非常的快。完全不用手动写多余的代码。

调用也非常简单,推荐使用SWIG。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

路边闲人2

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

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

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

打赏作者

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

抵扣说明:

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

余额充值