用python封装CTP接口

运行环境:ubuntu
上官网下载对应版本文件:http://www.sfit.com.cn/5_2_DocumentDown_6.htm
解压后是一些头文件和库文件,封装接口需要用到swig,所以新建两个指导文件thostmduserapi.i和thosttraderapi.i,这两个文件我也是从网上借鉴的,主要是对头文件、字符编码和数据结构处理的声明,要我自己写也写不出来,不过使用过程中没有发现什么毛病。
thostmduserapi.i

%module(directors="1") thostmduserapi
%{
#include "ThostFtdcMdApi.h"
#include <codecvt>
#include <locale>
#include <vector>
#include <string>
using namespace std;
#ifdef _MSC_VER
const static locale g_loc("zh-CN");
#else    
const static locale g_loc("zh_CN.GB18030");
#endif
%}

%feature("director") CThostFtdcMdSpi;
%ignore THOST_FTDC_VTC_BankBankToFuture;
%ignore THOST_FTDC_VTC_BankFutureToBank;
%ignore THOST_FTDC_VTC_FutureBankToFuture;
%ignore THOST_FTDC_VTC_FutureFutureToBank;
%ignore THOST_FTDC_FTC_BankLaunchBankToBroker;
%ignore THOST_FTDC_FTC_BrokerLaunchBankToBroker;
%ignore THOST_FTDC_FTC_BankLaunchBrokerToBank;
%ignore THOST_FTDC_FTC_BrokerLaunchBrokerToBank;


%typemap(out) char[ANY], char[] {
    const std::string &gb2312($1);
    std::vector<wchar_t> wstr(gb2312.size());
    wchar_t* wstrEnd = nullptr;
    const char* gbEnd = nullptr;
    mbstate_t state = {};
    int res = use_facet<codecvt<wchar_t, char, mbstate_t> >
        (g_loc).in(state,
            gb2312.data(), gb2312.data() + gb2312.size(), gbEnd,
            wstr.data(), wstr.data() + wstr.size(), wstrEnd);
 
    if (codecvt_base::ok == res)
    {
        wstring_convert<codecvt_utf8<wchar_t>> cutf8;
        std::string result = cutf8.to_bytes(wstring(wstr.data(), wstrEnd));       
        resultobj = SWIG_FromCharPtrAndSize(result.c_str(), result.size()); 
    }
    else
    {
        std::string result;
        resultobj = SWIG_FromCharPtrAndSize(result.c_str(), result.size()); 
    }
}
%typemap(in) char *[] {
  /* Check if is a list */
  if (PyList_Check($input)) {
    int size = PyList_Size($input);
    int i = 0;
    $1 = (char **) malloc((size+1)*sizeof(char *));
    for (i = 0; i < size; i++) {
      PyObject *o = PyList_GetItem($input, i);
      if (PyString_Check(o)) {
        $1[i] = PyString_AsString(PyList_GetItem($input, i));
      } else {
        free($1);
        PyErr_SetString(PyExc_TypeError, "list must contain strings");
        SWIG_fail;
      }
    }
    $1[i] = 0;
  } else {
    PyErr_SetString(PyExc_TypeError, "not a list");
    SWIG_fail;
  }
}

// This cleans up the char ** array we malloc'd before the function call
%typemap(freearg) char ** {
  free((char *) $1);
}
%include "ThostFtdcUserApiDataType.h"
%include "ThostFtdcUserApiStruct.h"
%include "ThostFtdcMdApi.h"

thosttraderapi.i

%module(directors="1") thosttraderapi 
%{ 
#include "ThostFtdcTraderApi.h"
#include <codecvt>
#include <locale>
#include <vector>
#include <string>
using namespace std;
#ifdef _MSC_VER
const static locale g_loc("zh-CN");
#else    
const static locale g_loc("zh_CN.GB18030");
#endif
%}

%typemap(out) char[ANY], char[] {
    const std::string &gb2312($1);
    std::vector<wchar_t> wstr(gb2312.size());
    wchar_t* wstrEnd = nullptr;
    const char* gbEnd = nullptr;
    mbstate_t state = {};
    int res = use_facet<codecvt<wchar_t, char, mbstate_t> >
        (g_loc).in(state,
            gb2312.data(), gb2312.data() + gb2312.size(), gbEnd,
            wstr.data(), wstr.data() + wstr.size(), wstrEnd);

    if (codecvt_base::ok == res)
    {
        wstring_convert<codecvt_utf8<wchar_t>> cutf8;
        std::string result = cutf8.to_bytes(wstring(wstr.data(), wstrEnd));       
        resultobj = SWIG_FromCharPtrAndSize(result.c_str(), result.size()); 
    }
    else
    {
        std::string result;
        resultobj = SWIG_FromCharPtrAndSize(result.c_str(), result.size()); 
    }
}

%typemap(in) char *[] {
  /* Check if is a list */
  if (PyList_Check($input)) {
    int size = PyList_Size($input);
    int i = 0;
    $1 = (char **) malloc((size+1)*sizeof(char *));
    for (i = 0; i < size; i++) {
      PyObject *o = PyList_GetItem($input, i);
      if (PyString_Check(o)) {
        $1[i] = PyString_AsString(PyList_GetItem($input, i));
      } else {
        free($1);
        PyErr_SetString(PyExc_TypeError, "list must contain strings");
        SWIG_fail;
      }
    }
    $1[i] = 0;
  } else {
    PyErr_SetString(PyExc_TypeError, "not a list");
    SWIG_fail;
  }
}

// This cleans up the char ** array we malloc'd before the function call
%typemap(freearg) char ** {
  free((char *) $1);
}
%feature("director") CThostFtdcTraderSpi; 
%ignore THOST_FTDC_VTC_BankBankToFuture;
%ignore THOST_FTDC_VTC_BankFutureToBank;
%ignore THOST_FTDC_VTC_FutureBankToFuture;
%ignore THOST_FTDC_VTC_FutureFutureToBank;
%ignore THOST_FTDC_FTC_BankLaunchBankToBroker;
%ignore THOST_FTDC_FTC_BrokerLaunchBankToBroker;
%ignore THOST_FTDC_FTC_BankLaunchBrokerToBank;
%ignore THOST_FTDC_FTC_BrokerLaunchBrokerToBank;  
%feature("director") CThostFtdcTraderSpi; 
%include "ThostFtdcUserApiDataType.h"
%include "ThostFtdcUserApiStruct.h" 
%include "ThostFtdcTraderApi.h"

这两个文件建立后,分别用

swig -threads -c++ -python thostmduserapi.i
swig -threads -c++ -python thosttraderapi.i

生成thostmduserapi_wrap.cxx和thosttraderapi_wrap.cxx
最后打包可以用

g++ -c -fPIC -I /usr/include/python3.8 thosttraderapi_wrap.cxx 

转为thosttraderapi_wrap.o 再用

g++ -shared thosttraderapi_wrap.o thosttraderapi_se.so -o _thosttraderapi.so -lpython3.8 

生成_thosttraderapi.so,最后这个-l***要看你具体的版本和路径,处理thostmduserapi_wrap.cxx也可以用同样的方法生成_thostmduserapi_se.so,其实thostmduserapi.py和thosttraderapi.py都是分别调用这两个生成的文件的。
网上有用distutils打包封装的,但我这个环境distutils.core 里面的函数无法识别.so文件,链接不了.so,不知道是不是我的问题。
最后

vi ~/.bashrc   export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/media/sda4/anotherfills/CTPobject 

把项目路径添加到库路径,要不然会提示找不到.so文件。
python调用时如果是linux系统可能会出现locale::facet::_S_create_c_locale name not valid 错误(这是第二行错误,第一行错误大概是runtime error这个意思),那是因为你系统的字符集不支持GB18030等,要新增对应字符支持,具体过程为1.locale -a 查看已配置的字符集,看有没有以上字符,如果没有的话用locale -m查看系统已安装了哪些字符集,修改/var/lib/locales/supported.d/zh-hans 文件添加,具体文件不同的系统可能不同,而且这个文件一般属主是root,要注意修改权限,注意添加的格式为zh_CN.GB18030 GB18030 而不是单单GB18030,这个很重要,最后sudo locale-gen 生成对应字符编码。
网上有说是用export LC_ALL="C"设置的,但我试了没用。
出现Decrypt handshake data failed的时候,请确保你的版本号不是测试版本,官方文档也是这么说的,开始我也是这个错误,然后换成生产版本就可以了。

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容