運行環(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)版本就可以了拾枣。