• 使用sipParseArgs/sipBuildResult进行python/C++对象的转换


    SIP库是用于python/C++对象互相转换的桥梁,由于python本身运行速度非常慢,所以很多第三方模块在底层会使用C++来编写,并提供python接口供python调用,在提供对象转换时,sipParseArgs和sipBuildResult是一对经常使用的函数,其中sipParseArgs用于将python对象转换成C++对象,而sipBuildResult则用于将C++对象转换成python对象,即PyObject,由于网络上关于它们的资料非常少,因此有必要在此记录一下,如果发现有任何错误,请在评论区留言告知。

    本文使用python3.8,SIP版本为6.0.3

    sipParseArgs

    其原型为int sipParseArgs(PyObject* sipParseErr, PyObject* obj, const char* format ...),

    返回值为非0时代表成功,为0时代表失败,obj代表需要解析的python对象,format代表解析规则(区分大小写),根据规则不同,format后面跟着的参数也不相同,具体如下:

    预定义参数意义:sipSelf:即python中的self。sipTypeDef:类型定义,即形如sipType_MyType的类型定义,代表一个完整的C++类。sipCpp:指向原始的C++对象的指针。sipRes:代表C++返回值。

    注意,你可以在format字符串中使用 () 来代表tuple, [] 来代表list, {}来代表dict, 例如 (id) 表示一个两个元素的tuple,第一个元素为int型,第二个元素为double型

    格式类型参数描述
    =size_tsize_t* out1提取size_t
    1P0Python objectPyObject** out1提取PyObject(猜测跳过parse过程直接返回了)
    aecharchar* out1从大小为1的bytes/string对象中提取char,e表示encoding方式,为A时代表ASCII,为L时代表Latin-1,为8时代表UTF-8
    bboolbool* out1提取bool
    ccharchar* out1从大小为1的bytes对象中提取char
    ddoubledouble* out1提取double
    ffloatfloat* out1提取float
    g字符串const char**, SIP_SSIZE_T* size从bytes对象中提取字符串,如果对象为None则返回nullptr和0
    hshortshort* out1提取short
    iintint* out1提取int
    llonglong* out1提取long
    munsigned longunsigned long* out1提取unsigned long
    nlong longlong long* out1提取long long
    ounsigned long longunsigned long long* out1提取unsigned long long
    sconst char*const char** out1提取const char*
    tunsigned shortunsigned short* out1提取unsigned short
    uunsigned intunsigned int* out1提取unsigned int
    vvoidvoid* out1提取void
    wwchar_twchar_t* out1从大小为1的string对象中提取wchar_t
    xwchar_t*字符串wchar_t** out1从string对象中提取\0结尾的宽字符串,如果对象为None则返回nullptr
    Aechar*字符串int out1, const char** out2从bytes/string对象中提取\0结尾的字符串,e代表encoding方式,为A时代表ASCII,为L时代表Latin-1,为8时代表UTF-8,如果对象为None则返回nullptr
    B联合类型PyObject** sipSelf, sipTypeDef typeDef, PyObject** sipCppsipSelf,sipCpp为输出参数,typeDef为输入参数
    E联合类型sipTypeDef typeDef, Enum* out1提取枚举类型值
    J0联合类型sipTypeDef typeDef, const T* out1, int* out1State 提取class类型值,out1State指示提取状态,out1可能存在默认值例如nullptr,使用完毕后应当使用sipReleaseType(T* out1, sipTypeDef typeDef, int out1State)释放out1对象
    J1联合类型sipTypeDef typeDef, const T* out1, int* out1State 提取class类型值,out1State指示提取状态,out1使用完毕后应当使用sipReleaseType(T* out1, sipTypeDef typeDef, int out1State)释放out1对象
    J8联合类型sipTypeDef typeDef, T* out1提取class类型值,out1可能存在默认值例如nullptr,无需释放out1对象
    J9联合类型sipTypeDef typeDef, T* out1提取class类型值,无需释放out1对象
    Lsigned charsigned char* out1提取signed char
    Munsigned charunsigned char* out1提取unsigned char
    Vvoidptrvoid**提取void*
    |----跟在该符号后面的是可选参数。可选参数即在C++头文件的函数声明中带有默认值的参数

    例子:编写一个python接口函数:

    假设有以下C++声明:

    1. class MyClass
    2. {
    3. public:
    4. int setInfo(const std::string& name, int value = -1);
    5. };

    现在为MyClass类的成员函数setInfo创建python接口 :

    1. static PyObject* invoke_MyClass_setInfo(PyObject* sipSelf, PyObject* sipArgs)
    2. {
    3. PyObject* sipParseErr = SIP_NULLPTR;
    4. const std::string* a0;
    5. int a0State = 0;
    6. int a1 = -1;
    7. MyClass* sipCpp;
    8. if (sipParseArgs(&sipParseErr, sipArgs, "BJ1|i", &sipSelf, sipType_MyClass, &sipCpp, sipType_std_string, &a0, &a0State, &a1))
    9. {
    10. int sipRes = sipCpp->setInfo(*a0, a1);
    11. sipReleaseType(const_cast(a0), sipType_std_string, a0State);
    12. return sipBuildResult(nullptr, "i", &sipRes); // or use PyLong_FromLong(sipRes) directly
    13. }
    14. return SIP_NULLPTR;
    15. }

    sipBuildResult

    其原型为PyObject* sipBuildResult(int* isErr, const char* format ...)

    format意义与sipParseArgs一致

  • 相关阅读:
    阿里架构阿里架构师手把手带你学Mybatis开源ORM框架“
    【高效的秘密】让k8s运维更高效-日志搜索脚本
    CURL踩坑记录
    Spring Cache 带你飞(一)
    Vue:生命周期
    Redis解决秒杀微服务抢购代金券超卖和同一个用户多次抢购
    【vue】axios封装拦截
    QT day2
    聊一聊 Rust 的 stack overflow
    HTML5期末考核大作业:基于Html+Css+javascript的网页制作(化妆品公司网站制作)
  • 原文地址:https://blog.csdn.net/yuchno1/article/details/126498691