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_t | size_t* out1 | 提取size_t |
1P0 | Python object | PyObject** out1 | 提取PyObject(猜测跳过parse过程直接返回了) |
ae | char | char* out1 | 从大小为1的bytes/string对象中提取char,e表示encoding方式,为A时代表ASCII,为L时代表Latin-1,为8时代表UTF-8 |
b | bool | bool* out1 | 提取bool |
c | char | char* out1 | 从大小为1的bytes对象中提取char |
d | double | double* out1 | 提取double |
f | float | float* out1 | 提取float |
g | 字符串 | const char**, SIP_SSIZE_T* size | 从bytes对象中提取字符串,如果对象为None则返回nullptr和0 |
h | short | short* out1 | 提取short |
i | int | int* out1 | 提取int |
l | long | long* out1 | 提取long |
m | unsigned long | unsigned long* out1 | 提取unsigned long |
n | long long | long long* out1 | 提取long long |
o | unsigned long long | unsigned long long* out1 | 提取unsigned long long |
s | const char* | const char** out1 | 提取const char* |
t | unsigned short | unsigned short* out1 | 提取unsigned short |
u | unsigned int | unsigned int* out1 | 提取unsigned int |
v | void | void* out1 | 提取void |
w | wchar_t | wchar_t* out1 | 从大小为1的string对象中提取wchar_t |
x | wchar_t*字符串 | wchar_t** out1 | 从string对象中提取\0结尾的宽字符串,如果对象为None则返回nullptr |
Ae | char*字符串 | 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** sipCpp | sipSelf,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对象 |
L | signed char | signed char* out1 | 提取signed char |
M | unsigned char | unsigned char* out1 | 提取unsigned char |
V | voidptr | void** | 提取void* |
| | -- | -- | 跟在该符号后面的是可选参数。可选参数即在C++头文件的函数声明中带有默认值的参数 |
例子:编写一个python接口函数:
假设有以下C++声明:
- class MyClass
- {
- public:
- int setInfo(const std::string& name, int value = -1);
- };
现在为MyClass类的成员函数setInfo创建python接口 :
- static PyObject* invoke_MyClass_setInfo(PyObject* sipSelf, PyObject* sipArgs)
- {
- PyObject* sipParseErr = SIP_NULLPTR;
- const std::string* a0;
- int a0State = 0;
- int a1 = -1;
- MyClass* sipCpp;
- if (sipParseArgs(&sipParseErr, sipArgs, "BJ1|i", &sipSelf, sipType_MyClass, &sipCpp, sipType_std_string, &a0, &a0State, &a1))
- {
- int sipRes = sipCpp->setInfo(*a0, a1);
- sipReleaseType(const_cast
(a0), sipType_std_string, a0State); - return sipBuildResult(nullptr, "i", &sipRes); // or use PyLong_FromLong(sipRes) directly
- }
- return SIP_NULLPTR;
- }
sipBuildResult
其原型为PyObject* sipBuildResult(int* isErr, const char* format ...)
format意义与sipParseArgs一致