用python封裝CTP接口

運行環(huán)境:ubuntu
上官網(wǎng)下載對應版本文件:http://www.sfit.com.cn/5_2_DocumentDown_6.htm
解壓后是一些頭文件和庫文件,封裝接口需要用到swig靶橱,所以新建兩個指導文件thostmduserapi.i和thosttraderapi.i百宇,這兩個文件我也是從網(wǎng)上借鑒的芙代,主要是對頭文件霞扬、字符編碼和數(shù)據(jù)結構處理的聲明山憨,要我自己寫也寫不出來焦蘑,不過使用過程中沒有發(fā)現(xiàn)什么毛病盯拱。
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都是分別調用這兩個生成的文件的拼卵。
網(wǎng)上有用distutils打包封裝的奢浑,但我這個環(huán)境distutils.core 里面的函數(shù)無法識別.so文件,鏈接不了.so腋腮,不知道是不是我的問題雀彼。
最后

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

把項目路徑添加到庫路徑壤蚜,要不然會提示找不到.so文件。
python調用時如果是linux系統(tǒng)可能會出現(xiàn)locale::facet::_S_create_c_locale name not valid 錯誤(這是第二行錯誤徊哑,第一行錯誤大概是runtime error這個意思)袜刷,那是因為你系統(tǒng)的字符集不支持GB18030等,要新增對應字符支持莺丑,具體過程為1.locale -a 查看已配置的字符集著蟹,看有沒有以上字符,如果沒有的話用locale -m查看系統(tǒng)已安裝了哪些字符集梢莽,修改/var/lib/locales/supported.d/zh-hans 文件添加萧豆,具體文件不同的系統(tǒng)可能不同,而且這個文件一般屬主是root,要注意修改權限昏名,注意添加的格式為zh_CN.GB18030 GB18030 而不是單單GB18030涮雷,這個很重要,最后sudo locale-gen 生成對應字符編碼轻局。
網(wǎng)上有說是用export LC_ALL="C"設置的洪鸭,但我試了沒用。
出現(xiàn)Decrypt handshake data failed的時候嗽交,請確保你的版本號不是測試版本卿嘲,官方文檔也是這么說的,開始我也是這個錯誤夫壁,然后換成生產(chǎn)版本就可以了拾枣。

?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市盒让,隨后出現(xiàn)的幾起案子梅肤,更是在濱河造成了極大的恐慌,老刑警劉巖邑茄,帶你破解...
    沈念sama閱讀 219,270評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件姨蝴,死亡現(xiàn)場離奇詭異,居然都是意外死亡肺缕,警方通過查閱死者的電腦和手機左医,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,489評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來同木,“玉大人浮梢,你說我怎么就攤上這事⊥罚” “怎么了秕硝?”我有些...
    開封第一講書人閱讀 165,630評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長洲尊。 經(jīng)常有香客問我远豺,道長奈偏,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,906評論 1 295
  • 正文 為了忘掉前任躯护,我火速辦了婚禮惊来,結果婚禮上,老公的妹妹穿的比我還像新娘棺滞。我一直安慰自己唁盏,他們只是感情好,可當我...
    茶點故事閱讀 67,928評論 6 392
  • 文/花漫 我一把揭開白布检眯。 她就那樣靜靜地躺著,像睡著了一般昆淡。 火紅的嫁衣襯著肌膚如雪锰瘸。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,718評論 1 305
  • 那天昂灵,我揣著相機與錄音避凝,去河邊找鬼。 笑死眨补,一個胖子當著我的面吹牛管削,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播撑螺,決...
    沈念sama閱讀 40,442評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼含思,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了甘晤?” 一聲冷哼從身側響起含潘,我...
    開封第一講書人閱讀 39,345評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎线婚,沒想到半個月后遏弱,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,802評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡塞弊,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,984評論 3 337
  • 正文 我和宋清朗相戀三年漱逸,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片游沿。...
    茶點故事閱讀 40,117評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡饰抒,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出奏候,到底是詐尸還是另有隱情循集,我是刑警寧澤,帶...
    沈念sama閱讀 35,810評論 5 346
  • 正文 年R本政府宣布蔗草,位于F島的核電站咒彤,受9級特大地震影響疆柔,放射性物質發(fā)生泄漏。R本人自食惡果不足惜镶柱,卻給世界環(huán)境...
    茶點故事閱讀 41,462評論 3 331
  • 文/蒙蒙 一旷档、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧歇拆,春花似錦鞋屈、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,011評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至输吏,卻和暖如春权旷,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背贯溅。 一陣腳步聲響...
    開封第一講書人閱讀 33,139評論 1 272
  • 我被黑心中介騙來泰國打工拄氯, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人它浅。 一個月前我還...
    沈念sama閱讀 48,377評論 3 373
  • 正文 我出身青樓译柏,卻偏偏與公主長得像,于是被迫代替她去往敵國和親姐霍。 傳聞我的和親對象是個殘疾皇子鄙麦,可洞房花燭夜當晚...
    茶點故事閱讀 45,060評論 2 355

推薦閱讀更多精彩內(nèi)容