pu369com

功能不够用?使用C++编写通达信插件及接入Python(二)

参考:https://zhuanlan.zhihu.com/p/613157262

一、准备工作(参考上一篇)

安装 VS2019 

安装pycharm

下载  http://help.tdx.com.cn/book.asp 《通达信DLL函数编程规范.rar》

二、下载python3.x的32位版本,,随便找个32位版就行了。

我准备下载Windows embeddable package (32-bit),然而下载速度感人,于是参考https://blog.csdn.net/m0_64336780/article/details/123534308

从 https://mirrors.huaweicloud.com/python/ 下载了   python-3.11.3.exe 安装

由于我已经安装了python 64 位的,所以安装后,要调整环境变量,将32位的环境变量调到上面,就切换成32位了。需要63位时,再将64位的环境变量调整到上面即可。

三、从   通达信DLL函数编程规范  里的项目开始

1.修改VS2019,勾选  windows10 SDK

2. 用Visual studio 打开 “TestPluginTCale.dsw”文件

出现“评审项目和解决方案更改”  ,直接 确定

出现迁移报告,存在错误

3.解决BUG - 修改项目属性

在解决方案资源管理器中,项目的  TestPluginTCale上右键 属性  

在弹出框的  配置属性  c/c++  常规  中,将  “调试信息格式”的选项更改为“程序数据库(/Zi)”

               在 配置属性  c/c++  代码生成  中 “启用最小重新生成”设为“否(/Gm-)”

               在 配置属性  c/c++  代码生成  中 “启用函数级链接”设为“是(/Gy)”

               在 配置属性  链接器  常规   附加库目录 

             输入 D:\Python\python31132\libs  (根据你的32位python安装位置确定)之后,值变为:D:\Python\python31132\libs;%(AdditionalLibraryDirectories)

              如果添加后,vs报错,说什么python3x_d找不到,那就在安装目录下的libs(不是lib)里找到python3x.lib,复制一份改个名,改成vs要求的文件名就行了。总之,vs说差什么文件,改成vs要求的文件名就可以了。

四、改写TCalcFuyncSets.cpp如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
#include "stdafx.h"
 
#include "TCalcFuncSets.h"
 
#include "Python.h" //严重注意,一定要include这个。
 
//生成的dll请拷贝到通达信安装目录的T0002/dlls/内,再在公式管理器进行绑定
 
//有人老是无法正常绑定,这里给出两种解决方案,任选其一,本人喜欢第二种
 
//1、不运行快捷方式,直接点开通达信目录里的执行文件
 
//2、运行快捷方式,但需要将快捷方式里的起始位置清空
 
void CallFunction(int DataLen, float* pfOUT, float* pfINa, float* pfINb, float* pfINc, char* funcName)
 
{
 
    //填上自己的32位python安装目录,当然,你的python也可以直接装在这个目录下。
 
    Py_SetPythonHome(L"C:\\Python31132"); //用这个版本的python来执行python文件
 
    Py_Initialize(); //初始化python接口
 
 
 
    //初始化使用的变量
 
    PyObject* pModule = NULL;
 
    PyObject* pFunc = NULL;
 
    PyObject* pName = NULL;
 
 
 
    //获得绝对路径,保证可以访问到 .py文件
 
    //这里需要注意的时候,运行通达信时,找到的路径是通达信的安装路径,所以需要把子路径补充进去
 
    PyRun_SimpleString("import os,sys");
 
    PyRun_SimpleString("sys.path.append(os.getcwd()+ '/T0002/dlls/')");
 
 
 
    //当前的测试python文件名是TDXPYDLL.py,只需要写文件的名称就可以了。也可以换个名字,但需要把名字改了。
 
    pModule = PyImport_ImportModule("TDXPYDLL");
 
 
 
    //获取调用的函数
 
    pFunc = PyObject_GetAttrString(pModule, funcName);
 
 
 
    //定义一个与数组等长的PyList对象数组
 
    PyObject* HList = PyList_New(DataLen);
 
    PyObject* LList = PyList_New(DataLen);
 
    PyObject* CList = PyList_New(DataLen);
 
 
 
    //定义一个元组,有四个变量的参数元组
 
    PyObject* paramTuple = PyTuple_New(4);
 
 
 
    //PyList对象的每个元素赋值PyList_Size(HList),以便传入价格序列
 
    for (int i = 0; i < DataLen; i++)
 
    {
 
        PyList_SetItem(HList, i, Py_BuildValue("f", pfINa[i]));
 
        PyList_SetItem(LList, i, Py_BuildValue("f", pfINb[i]));
 
        PyList_SetItem(CList, i, Py_BuildValue("f", pfINc[i]));
 
    }
 
 
 
    //向python传参数
 
    PyTuple_SetItem(paramTuple, 0, Py_BuildValue("i", DataLen));//第一个参数
 
    PyTuple_SetItem(paramTuple, 1, HList); //1:表示序号。第二个参数。
 
    PyTuple_SetItem(paramTuple, 2, LList); //2:表示序号。第三个参数。
 
    PyTuple_SetItem(paramTuple, 3, CList); //3:表示序号。第四个参数。
 
 
 
    //使用C++的python接口调用该函数
 
    PyObject* pReturn = PyObject_CallObject(pFunc, paramTuple);
 
 
 
    if (pReturn) //类型检查
 
    {
 
        for (int i = 0; i < DataLen; i++)
 
        {
 
            //PyObject *Item = PyList_GetItem(pReturn, i);//获取List对象中的每一个元素
 
            float result;
 
            PyArg_Parse(PyList_GetItem(pReturn, i), "f", &result);//f表示转换成浮点变量
 
            pfOUT[i] = result;
 
        }
 
    }
 
    ////用完接口得放掉,呼应前面的Py_Initialize();
 
    Py_Finalize();
 
 
 
}
 
 
 
void TestPlugin1(int DataLen, float* pfOUT, float* pfINa, float* pfINb, float* pfINc)
 
{
 
    CallFunction(DataLen, pfOUT, pfINa, pfINb, pfINc, "TestPlugin1");
 
}
 
 
 
void TestPlugin2(int DataLen, float* pfOUT, float* pfINa, float* pfINb, float* pfINc)
 
{
 
    CallFunction(DataLen, pfOUT, pfINa, pfINb, pfINc, "TestPlugin2");
 
}
 
 
 
 
 
void TestPlugin3(int DataLen, float* pfOUT, float* pfINa, float* pfINb, float* pfINc)
 
{
 
    CallFunction(DataLen, pfOUT, pfINa, pfINb, pfINc, "TestPlugin3");
 
}
 
 
 
 
 
void TestPlugin4(int DataLen, float* pfOUT, float* pfINa, float* pfINb, float* pfINc)
 
{
 
    CallFunction(DataLen, pfOUT, pfINa, pfINb, pfINc, "TestPlugin4");
 
}
 
 
 
void TestPlugin5(int DataLen, float* pfOUT, float* pfINa, float* pfINb, float* pfINc)
 
{
 
    CallFunction(DataLen, pfOUT, pfINa, pfINb, pfINc, "TestPlugin5");
 
}
 
 
 
void TestPlugin6(int DataLen, float* pfOUT, float* pfINa, float* pfINb, float* pfINc)
 
{
 
    CallFunction(DataLen, pfOUT, pfINa, pfINb, pfINc, "TestPlugin6");
 
}
 
 
 
//加载的函数,这里的序号和上面函数对应,这只是绑了六个,想多绑的自己加
 
PluginTCalcFuncInfo g_CalcFuncSets[] =
 
{
 
{1,(pPluginFUNC)&TestPlugin1},
 
{2,(pPluginFUNC)&TestPlugin2},
 
{3,(pPluginFUNC)&TestPlugin3},
 
{4,(pPluginFUNC)&TestPlugin4},
 
{5,(pPluginFUNC)&TestPlugin5},
 
{6,(pPluginFUNC)&TestPlugin6},
 
{0,NULL},
 
};
 
 
 
//导出给TCalc的注册函数
 
BOOL RegisterTdxFunc(PluginTCalcFuncInfo** pFun)
 
{
 
    if (*pFun == NULL)
 
    {
 
        (*pFun) = g_CalcFuncSets;
 
        return TRUE;
 
    }
 
    return FALSE;
 
}

  结果提示没头文件,python.h

参考:https://blog.csdn.net/JLinkTwo/article/details/87917504  用   pip install python-dev  安装

再参考:https://blog.csdn.net/weixin_44575152/article/details/114186758     对 配置属性  VC++目录   外部包含目录   进行编辑,  加入了  python.h所在目录: D:\Python\python31132\include

生成解决方案
又提示: 无法打开文件“python311_d.lib

于是将D:\Python\python31132\libs下的 python311.lib 复制 为  python311_d.lib

终于成功了

到了这里, Dll写完了,编译成32位TestPluginTCale.dll放到T0002/dlls目录里。然后创建一个TDXPYDLL.py,该文件同样需要放在T0002/dlls内。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
def TestPlugin1(N: int, H: list, L: list, C: list):
    for i in range(1, N):
        result[i] = i
    return result
def TestPlugin2(N: int, H: list, L: list, C: list):
    for i in range(1, N):
        result[i] = i
    return result
def TestPlugin3(N: int, H: list, L: list, C: list):
    for i in range(1, N):
        result[i] = i
    return result
def TestPlugin4(N: int, H: list, L: list, C: list):
    for i in range(1, N):
        result[i] = i
    return result
def TestPlugin5(N: int, H: list, L: list, C: list):
    for i in range(1, N):
        result[i] = i
    return result
def TestPlugin6(N: int, H: list, L: list, C: list):
    for i in range(1, N):
        result[i] = i
    return result

按上一篇 绑定DLL,写demo公式,结果通达信死机

后来发现 dll 源文件 中有一句忘记改了:

Py_SetPythonHome(L"C:\\Python31132"); //用这个版本的python来执行python文件

改为Py_SetPythonHome(L"D:\\Python\\python31132");

重新生成dll,替换,不要从快捷方式而是从所在目录中启动TdxW.exe,看似成功了,python脚本似乎也运行了。然而得不到输出

又参照网贴,将TestPlugin2改为如下代码:

1
2
3
4
5
6
def TestPlugin2(N: int, H: list, L: list, C: list):
    result=[]
    for i in range(1, N):
        temp = i * 6.0
        result.append(temp)   
    return result

  终于成功了

上面的temp也可以:temp = (H[i]+L[i]+C[i])*1.0

说明:在python代码中,可以  import os  

然后用os.mkdir('你的目录')在通达信运行目录中生成文件夹

或者用

1
2
log = open('r.txt', 'a')
print(“相关数据”, file=log)

  更明显地看到效果。

 

posted on   pu369com  阅读(1861)  评论(0编辑  收藏  举报

相关博文:
阅读排行:
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
历史上的今天:
2020-04-17 python查看乱码
2020-04-17 使用 Python 查看局域网内存活主机
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

导航

统计

点击右上角即可分享
微信分享提示