1. 環境準備:
1) VS 2015html
2) Python 3.7 64位python
3) CTP API (從 http://www.sfit.com.cn/5_2_DocumentDown.htm 下載,此文檔使用的是 http://www.sfit.com.cn/APIHistory1.html 下載的 6.3.11_20180109 版本)c++
error.dtd error.xml ThostFtdcMdApi.h ThostFtdcTraderApi.h ThostFtdcUserApiDataType.h ThostFtdcUserApiStruct.h thostmduserapi.dll thostmduserapi.lib thosttraderapi.dll thosttraderapi.lib
4) Swingwindows
下載地址: https://sourceforge.net/projects/swig/files/。本文用的是 3.0.12 版本api
使用方式:下載完成後,解壓縮,而後 將存放的文件路徑 加到 系統變量 PATH 中。多線程
5) liviconv 庫工具
這個庫主要適用於字節編碼轉換,由於CTP的中文是GB2312編碼,轉換爲UTF-8編碼,適合python輸出post
編譯方法:按照 https://blog.csdn.net/ghevinn/article/details/9825765 步驟編碼
備註:1. 本次使用的是最新的 1.16 版本,能夠經過 http://ftp.gnu.org/pub/gnu/libiconv/, 查詢當前可用的版本spa
2. VS 編譯生成的是 Release x64 位。
2. 經過Swig獲得python接口文件
在剛剛下載獲得的API文件夾20180109_tradeapi64_windows內,新建文件 thostmduserapi.i,內容以下
%module(directors="1") thostmduserapi %{ #include "ThostFtdcMdApi.h" #include "iconv.h" %} %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[] { if ($1) { iconv_t cd = iconv_open("utf-8", "gb2312"); if (cd != reinterpret_cast<iconv_t>(-1)) { char buf[4096] = {}; const char **in = (const char **)&$1; char *out = buf; size_t inlen = strlen($1), outlen = 4096; if (iconv(cd, in, &inlen, &out, &outlen) != static_cast<size_t>(-1)) { size_t size = outlen; while (size && (buf[size - 1] == '\0')) --size; resultobj = SWIG_FromCharPtrAndSize(buf, size); } iconv_close(cd); } } } %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"
這是一個接口文件,用於告訴swig爲哪些類和方法建立接口。打開windows cmd工具,cd到當前目錄\20180109_tradeapi_windows下。 在cmd中運行命令
swig -threads -c++ -python thostmduserapi.i
等到運行完成後,能夠看到當前目錄下生成了
thostmduserapi_wrap.h thostmduserapi_wrap.cxx thostmduserapi.py
.h和.cx文件是用於包裝原來C++接口的文件,下面要用。.py文件是python調用方法的接口文件。
3. 經過C++獲得python可調用的pyd動態庫
在當前文件夾下創建一個C++工程,工程的應用程序類型選DLL,工程名爲_thostmduserapi.i(建工程的步驟也可參考https://blog.csdn.net/pjjing/article/details/53186394這篇文章第3步開頭),
須要注意幾點:1)工程建64位dll類型,2)運行庫選多線程(/MT)。而後將以下文件拷貝到_thostmduserapi\文件夾下:
ThostFtdcMdApi.h ThostFtdcUserApiDataType.h ThostFtdcUserApiStruct.h thostmduserapi.lib thostmduserapi_wrap.h thostmduserapi_wrap.cxx libiconv.lib iconv.h
在c++工程中添加現有項,將這些文件所有添加到工程中去。下面還要作幾步:
1)將你安裝的python下include文件夾的路徑添加至C++附加包含目錄。個人路徑是 D:\Program Files (x86)\Python37\include;,C++附加包含目錄在工程-屬性-配置屬性-c/c++。
2)將你安裝的python中python37.lib添加至工程附加依賴項中。個人lib路徑是 D:\Program Files (x86)\Python37\libs\python37.lib;,附加依賴項在 工程-屬性-配置屬性-連接器-輸入。
3)這樣所有完成以後,選擇Release版本 64位,咱們按F7編譯,在\_thostmduserapi\Release目錄底下可見_thostmduserapi.dll動態庫文件,說明編譯成功,將其重命名爲_thostmduserapi.pyd,這樣CTP Python API就編譯成功了。
【有可能須要將 iconv.h 和 libIconv.lib 將放在待生成的 Release 目錄下】
若是編譯出現一些問題,能夠百度解決。可能涉及到要修改pyconfig.h,object.h,Python.h三個文件。
問題1: 找不到 沒法將參數 2 從「char **」轉換爲「const char **」, 原文的 thostmduserapi.i 在 VS2015 編譯時,有問題,須要將 char **in = &$1; 改成 const char **in = (const char **)&$1;
問題2:沒法解析的外部符號 __imp_setlocale,解決辦法:在 thostmduserapi_wrap.cxx 的頭部加上 #pragma comment(lib,"msvcrtd.lib")
問題3:默認庫「library」與其餘庫的使用衝突;使用 /NODEFAULTLIB:library,解決辦法:(https://blog.csdn.net/larry_zeng1/article/details/86679869)
1.右擊工程 - 屬性 」配置屬性 - 連接器 - 輸入 - 忽略特定庫「,添加 」libcmtd.lib「;
或 2.右擊工程 - 屬性 」配置屬性 - 連接器 - 命令行」 添加: /NODEFAULTLIB:"libcmtd.lib"
4. Python Demo
經過在c++中引入字符轉碼爲utf-8,如今中文已經能夠直接輸出了,詳見demo。
新建文件md_demo_demo.py,注意文件同目錄底下要有以下三個文件:
thostmduserapi.py thostmduserapi.dll _thostmduserapi.pyd