【类CTP C++ API 转 Python】Windows64环境中使用SWIG转换行情相关API(避坑)
前置条件:
- VS2022
- Python环境(用conda创建或者下载对应版本的环境都可)
- SWIG
- iconv文件(.lib与.h)从借刀破提供的仓库中下载
(注:本文遵循景色教程中版本使用Python3.7.2与SWIG4.0.0)
xxx.i文件模板为:
/*
* xxxapi.i
* 用 SWIG 把 C++ API 封装成 Python 模块
*/
/*
* 1. 定义模块名
*
* Python 导入方式:
* import xxxmdapi
*
* directors="1":
* 开启 Python 继承 C++ 回调类的能力。
* 因为 XXXSpi 里面有 OnRspXXX / OnRtnXXX 这类 virtual 回调。
*/
%module(directors="1") xxxapi
/*
* 2. 这些 include 会原样写进生成的 xxxapi_wrap.cxx
*
* 作用:
* 让 C++ 编译器知道 XXXApi、XXXSpi、各种行情结构体的定义。
*/
%{
#include "XXX.h"
#include "XXXApi.h"
#include "iconv.h"
%}
/*
* 3. char[] / char* 输出编码转换
*
* 国产行情接口很多 char 字段可能是 GB2312/GBK。
* Python3 使用 UTF-8。
*
* 这段会把 C++ char 数组转换成 Python str。
* 如果字段只是 InstrumentID、ExchangeID 这种 ASCII,保留也没问题。
*/
%typemap(out) char[ANY], char[] {
if ($1) {
iconv_t cd = iconv_open("utf-8", "gb2312");
if (cd != reinterpret_cast<iconv_t>(-1)) {
char buf[4096] = {};
char **in = &$1;
char *out = buf;
size_t inlen = strlen($1);
size_t outlen = sizeof(buf);
if (iconv(cd, (const char **) in, &inlen, &out, &outlen) != static_cast<size_t>(-1)) {
size_t size = strlen(buf);
resultobj = SWIG_FromCharPtrAndSize(buf, size);
}
iconv_close(cd);
}
}
}
/*
* 4. 指定回调类启用 director
*
* 这是最关键的一行。
* 没有它,Python 继承 XXXSpi 后,C++ 回调不会进入 Python。
*/
%feature("director") XXXSpi;
/*
* 5. SWIG 标准类型支持
*/
%include "stdint.i" // 支持 uint16_t / uint32_t / int64_t 等
%include "typemaps.i" // 支持常见指针参数转换
%include "std_string.i" // 支持 std::string
/*
* 6. 真正暴露给 Python 的头文件
*
* 顺序:先结构体,后 API。
*/
%include "XXX.h"
%include "XXX.h"
运行swig命令时想切换到想要使用的python环境下
visual studio操作时注意细节
-
问题:生成的_swag.cxx文件中报错信息为未定义标识符 “SWIG_FromCharPtrAndSize”
解决方法:
将SWIG_FromCharPtrAndSize改为PyUnicode_FromStringAndSize
原因:PyString_FromStringAndSize is replaced with PyUnicode_FromStringAndSize in Python3, and SWIG_FromCharPtrAndSize will choose the right one with the check “#if PY_VERSION_HEX >= 0x0300000”.
出处 -
生成解决方案报错:“size_t libiconv(libiconv_t,char **,size_t *,char **,size_t *)”: 无法将参数 2 从“const char **”转换为“char **”
if (iconv(cd,(const char **)in, &inlen, &out, &outlen) != static_cast<size_t>(-1))一句中删除(const char **) -
demo中报错:swig/python detected a memory leak of type ‘uint32_t *’, no destructor found.
.i文件中配置加入SWIG,模板中第5点 -
python list问题,在.i中加入具体处理方式 转换list(根据具体代码)
-
运行demo时,if判断中一个常量未定义
解决方法:
需要在.i中使用constant命令导出
原因:
在cpp文件中#define定义的常量不一定会被自动导出
更多推荐


所有评论(0)