使用自定义指标和 C++ DLL 时访问冲突读取错误和 MT4 崩溃
Access violation read error and MT4 crash when using custom indicator and C++ DLL
我正在编写一个从 C++ DLL 调用函数的指示器。我只需要将收盘价传递给 DLL 和 return 来自 DLL 的字符串。
MQL4 代码:
#import "PythonZones.dll"
void CalculateZones(double &data[], double quantile, int arraySize,char&[]);
#import
#property indicator_chart_window
char buffer[4096];
input color M5color = clrTurquoise;
input int WINDOW = 446;
input double PARAM_SHIFT = 0.14;
int start()
{
if (IsNewBar()){
double data[];
ArrayResize(data,WINDOW);
Rate(data,WINDOW);
Print(data[0]);
CalculateZones(data,PARAM_SHIFT ,WINDOW,buffer);
string zones = CharArrayToString(buffer);
Print(zones);
}
return(0);
}
void Rate(double &out[],int len){
for(int i=(len - 1);i>-1;i--){
double close = iClose(NULL,0,i+1);
out[i] = close;
}
}
和 C++ DLL 代码:
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
//#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION
#include <windows.h>
#include <string>
#include <stdlib.h>
#include <stdio.h>
#include "Python.h"
#include "numpy/arrayobject.h"
//----
#define MT4_EXPFUNC __declspec(dllexport)
PyObject *Amanda;
PyObject *AmandaZones;
BOOL APIENTRY DllMain(HANDLE hModule,DWORD ul_reason_for_call,LPVOID lpReserved)
{
//----
switch(ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
Py_Initialize();
import_array1(-1);
PyObject *pName;
pName = PyString_FromString("Amanda");
Amanda = PyImport_Import(pName);
Py_DECREF(pName);
if (Amanda != NULL){
AmandaZones = PyObject_GetAttrString(Amanda, "CalculateZones");
if (AmandaZones == NULL){
OutputDebugString("Failed to get desired func.");
}
}else{
OutputDebugString("Failed to load Amanda.");
}
OutputDebugString("Attached.");
break;
case DLL_THREAD_ATTACH:
break;
case DLL_THREAD_DETACH:
break;
case DLL_PROCESS_DETACH:
Py_DECREF(Amanda);
Py_DECREF(AmandaZones);
Py_Finalize();
break;
}
//----
return(TRUE);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
MT4_EXPFUNC void __stdcall CalculateZones(double *data, double quantile, int arraySize,char *buffer)
{
if (arraySize < 0) return;
npy_intp npy_arraysize;
npy_arraysize = arraySize;
PyObject *q = PyFloat_FromDouble(quantile);
PyObject *np_value = PyArray_SimpleNewFromData(1, &npy_arraysize, NPY_DOUBLE, data);
Py_INCREF(np_value);;
Py_INCREF(q);;
PyObject *pArgs = PyTuple_New(2);
PyTuple_SetItem(pArgs, 0, np_value);
PyTuple_SetItem(pArgs, 1, q);
PyObject *pResult = PyObject_CallObject(AmandaZones, pArgs);
Py_DECREF(pArgs);
Py_DECREF(np_value);
Py_DECREF(q);
char* res = PyString_AsString(pResult);
Py_DECREF(pResult);
strcpy(buffer,res);
}
指标完美运行,但是当我从图表中删除指标并再次添加时,它不再工作并且 return 出现错误 "Access violation read"。
而且当我将它与 Strategy Tester 一起使用时,MetaTrader 崩溃但没有记录任何错误。
我认为问题出在数组引用上。我尝试使用 struct
而不是数组来尝试它,但我无法以任何方式编译它,因为我不太了解 MQL4 或 C++。
我该如何解决这个问题?
Q: How can I solve the problem?
使用 string
-s 的 MQL4 / DLL 集成是一个疯狂的旅程...
然而,第一步应该是修复 #import
调用签名,其中提供了供 MQL4 编译器使用的接口详细信息:
#import "PythonZones.dll"
void CalculateZones( double &data[],
double quantile,
int arraySize,
char &buffer[] // this line is a suspect for mystifying compiler
);
#import
如果修复调用签名以满足 DLL 发布的调用接口没有帮助(如果没有 DLL-Under-Test 的副本我们无法测试),您需要专家对于这样的双系统集成(具有双域专业知识,C++ 不足以使 MQL4 编排工作)。
我祈祷你用修复的 #import
呼号就能解决问题。数十人 * 年的双域故障排除告诉我这样祈祷的原因。
问题出在 numpy
包上。在C++
中使用时不应初始化两次。 Py_finilize()
无法正常工作并且不会删除 numpy
模块对象。我从这里解决https://github.com/numpy/numpy/issues/8097
我正在编写一个从 C++ DLL 调用函数的指示器。我只需要将收盘价传递给 DLL 和 return 来自 DLL 的字符串。
MQL4 代码:
#import "PythonZones.dll"
void CalculateZones(double &data[], double quantile, int arraySize,char&[]);
#import
#property indicator_chart_window
char buffer[4096];
input color M5color = clrTurquoise;
input int WINDOW = 446;
input double PARAM_SHIFT = 0.14;
int start()
{
if (IsNewBar()){
double data[];
ArrayResize(data,WINDOW);
Rate(data,WINDOW);
Print(data[0]);
CalculateZones(data,PARAM_SHIFT ,WINDOW,buffer);
string zones = CharArrayToString(buffer);
Print(zones);
}
return(0);
}
void Rate(double &out[],int len){
for(int i=(len - 1);i>-1;i--){
double close = iClose(NULL,0,i+1);
out[i] = close;
}
}
和 C++ DLL 代码:
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
//#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION
#include <windows.h>
#include <string>
#include <stdlib.h>
#include <stdio.h>
#include "Python.h"
#include "numpy/arrayobject.h"
//----
#define MT4_EXPFUNC __declspec(dllexport)
PyObject *Amanda;
PyObject *AmandaZones;
BOOL APIENTRY DllMain(HANDLE hModule,DWORD ul_reason_for_call,LPVOID lpReserved)
{
//----
switch(ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
Py_Initialize();
import_array1(-1);
PyObject *pName;
pName = PyString_FromString("Amanda");
Amanda = PyImport_Import(pName);
Py_DECREF(pName);
if (Amanda != NULL){
AmandaZones = PyObject_GetAttrString(Amanda, "CalculateZones");
if (AmandaZones == NULL){
OutputDebugString("Failed to get desired func.");
}
}else{
OutputDebugString("Failed to load Amanda.");
}
OutputDebugString("Attached.");
break;
case DLL_THREAD_ATTACH:
break;
case DLL_THREAD_DETACH:
break;
case DLL_PROCESS_DETACH:
Py_DECREF(Amanda);
Py_DECREF(AmandaZones);
Py_Finalize();
break;
}
//----
return(TRUE);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
MT4_EXPFUNC void __stdcall CalculateZones(double *data, double quantile, int arraySize,char *buffer)
{
if (arraySize < 0) return;
npy_intp npy_arraysize;
npy_arraysize = arraySize;
PyObject *q = PyFloat_FromDouble(quantile);
PyObject *np_value = PyArray_SimpleNewFromData(1, &npy_arraysize, NPY_DOUBLE, data);
Py_INCREF(np_value);;
Py_INCREF(q);;
PyObject *pArgs = PyTuple_New(2);
PyTuple_SetItem(pArgs, 0, np_value);
PyTuple_SetItem(pArgs, 1, q);
PyObject *pResult = PyObject_CallObject(AmandaZones, pArgs);
Py_DECREF(pArgs);
Py_DECREF(np_value);
Py_DECREF(q);
char* res = PyString_AsString(pResult);
Py_DECREF(pResult);
strcpy(buffer,res);
}
指标完美运行,但是当我从图表中删除指标并再次添加时,它不再工作并且 return 出现错误 "Access violation read"。
而且当我将它与 Strategy Tester 一起使用时,MetaTrader 崩溃但没有记录任何错误。
我认为问题出在数组引用上。我尝试使用 struct
而不是数组来尝试它,但我无法以任何方式编译它,因为我不太了解 MQL4 或 C++。
我该如何解决这个问题?
Q: How can I solve the problem?
使用 string
-s 的 MQL4 / DLL 集成是一个疯狂的旅程...
然而,第一步应该是修复 #import
调用签名,其中提供了供 MQL4 编译器使用的接口详细信息:
#import "PythonZones.dll"
void CalculateZones( double &data[],
double quantile,
int arraySize,
char &buffer[] // this line is a suspect for mystifying compiler
);
#import
如果修复调用签名以满足 DLL 发布的调用接口没有帮助(如果没有 DLL-Under-Test 的副本我们无法测试),您需要专家对于这样的双系统集成(具有双域专业知识,C++ 不足以使 MQL4 编排工作)。
我祈祷你用修复的 #import
呼号就能解决问题。数十人 * 年的双域故障排除告诉我这样祈祷的原因。
问题出在 numpy
包上。在C++
中使用时不应初始化两次。 Py_finilize()
无法正常工作并且不会删除 numpy
模块对象。我从这里解决https://github.com/numpy/numpy/issues/8097