Передача двумерных массивив в DLL и обратно

 

Наверно тут такой вопрос уже поднимался, но я не мог найти ответа. Я не совсем знаком с mql4 и c++, поэтому будет благодарен ответам показывющим как правильно поступить в моём случае. Итак, DLL функция проста:

MT4_EXPFUNC void __stdcall Arr( const int n1, const int n2, double ** x)

{ x[0][0]=1.0;}

В mql4 такой код:

...

#import "Arr.dll"
void Arr(int n1, int n2, double x[][]);
#import

...

int start(){

...

int n2=10;

double myArray[][n2];

// вычисляем myArray

Arr(n1,n2,myArray);

...

Метатрейдер ломается с критической ошибкой. В прошлом успешно пользовался одномерными массивами и DLL. Скажите что не так делаю и покажите правильный код. Заранее спасибо.

 

Пробовал так в DLL

MT4_EXPFUNC void __stdcall Arr( const int n1, const int n2, double *x[])

{ x[0][0]=1.0;}

Всё равно краш.

 
fiqe :

Пробовал так в DLL

MT4_EXPFUNC void __stdcall Arr( const int n1, const int n2, double *x[])

{ x[0][0]=1.0;}

Всё равно краш.

ИМХО, указатель надо просто передавать на "double", без всяких скобок и "указателей на указатель". Поскольку всякий многомерный массив на самом деле одномерный, по крайней мере в Си. :)

Мне ни разу не приходилось делать таких вещей, чтоб нужно было передавать из MT4 массивы размерности больше единицы (если нужна действительно сложная обработка, она выносится целиком в DLL, где происходит раз в 10 быстрее, чем в MQL4), но появись нужда в 2D-массиве между MT4 и DLL, я бы обошелся одномерным, адресуясь в нем так: x[n2*posX+posY], где "n2" - размерность массива по оси Y (второму индексу), posX и posY - соотрественно первый и второй индексы. Можно и наоборот, адресоваться по первой размерности: x[n1*posY+posX]. Главное, использовать везде одинаковый формат обращения (по какой размерности обрабатывать массив). При необходимости, тем же путем можно сделать хоть 10-мерный массив. И не прийдется ломать голову, как протолкнуть его из одной системы в другую.

 
ZombieJesus :
fiqe :

Пробовал так в DLL

MT4_EXPFUNC void __stdcall Arr( const int n1, const int n2, double *x[])

{ x[0][0]=1.0;}

Всё равно краш.

ИМХО, указатель надо просто передавать на "double", без всяких скобок и "указателей на указатель". Поскольку всякий многомерный массив на самом деле одномерный, по крайней мере в Си. :)

Мне ни разу не приходилось делать таких вещей, чтоб нужно было передавать из MT4 массивы размерности больше единицы (если нужна действительно сложная обработка, она выносится целиком в DLL, где происходит раз в 10 быстрее, чем в MQL4), но появись нужда в 2D-массиве между MT4 и DLL, я бы обошелся одномерным, адресуясь в нем так: x[n2*posX+posY], где "n2" - размерность массива по оси Y (второму индексу), posX и posY - соотрественно первый и второй индексы. Можно и наоборот, адресоваться по первой размерности: x[n1*posY+posX]. Главное, использовать везде одинаковый формат обращения (по какой размерности обрабатывать массив). При необходимости, тем же путем можно сделать хоть 10-мерный массив. И не прийдется ломать голову, как протолкнуть его из одной системы в другую.

Спасибо за ответ. В крайнем случае прибегу к вашим рекомендациям.

Пробовал так в DLL

MT4_EXPFUNC void __stdcall Arr( const int n1, const int n2, double *x)

{ x[0][0]=1.0;}

MSVC даёт ошибку

error: expression must have pointer-to-object type in x[0][0]=1.0;

Апдейт: После долгих поисков на инете, я заключил что есть три основных способа передачи двумерных массивов в DLL функции:

1. void Arr( const int n1, const int n2, double **x) - вызывает краш метатрейдера

2. void Arr( const int n1, const int n2, double *x[]) - вызывает краш метатрейдера

3. void Arr( const int n1, const int n2, double *x[100]) - ещё не пробовал, но это будет не самым елегантным решением так как размеры массива у меня задаются в эксперте

Уважаемые программисты, пожалуйста посмотрите на мое первое сообщение и скажите почему MetaTraider крашит.

 

Пожалуйста, оформляйте код, в этом случае вероятность прочтения гораздо выше. На картинке видно, как я это сделал:


 
fiqe :

Пробовал так в DLL

MT4_EXPFUNC void __stdcall Arr( const int n1, const int n2, double *x)

{ x[0][0]=1.0;}

MSVC даёт ошибку

error: expression must have pointer-to-object type in x[0][0]=1.0;

Апдейт: После долгих поисков на инете, я заключил что есть три основных способа передачи двумерных массивов в DLL функции:

1. void Arr( const int n1, const int n2, double **x) - вызывает краш метатрейдера

2. void Arr( const int n1, const int n2, double *x[]) - вызывает краш метатрейдера

3. void Arr( const int n1, const int n2, double *x[100]) - ещё не пробовал, но это будет не самым елегантным решением так как размеры массива у меня задаются в эксперте

Уважаемые программисты, пожалуйста посмотрите на мое первое сообщение и скажите почему MetaTraider крашит.

Без задания размерности массива в DLL (а она в вышеприведенной функции никак не задается, выражение "double *x" с размерностями вообще не связано, это просто указатель на данные соответсвующего типа. Сколько их, и какой размерности, его не касается) к массиву в принципе невозможно корректно обратиться! Что касается примеров 1,2 и 3, в них всех вообще-то подразумевается, что массив сложный - указатель на массив указателей(!), уже каждый из которых указывает на числа. Это имеет смысл только если в строках или столбцах количество чисел различается (это количество должно храниться в отдельном массиве/структуре) и видимо не соответсвует простой модели в МТ (размерности всех строк и всех столбцов одинаковы), из-за такого грубого несоответсвия типов странно было бы, если бы МТ не падал. Проверь так:

MT4_EXPFUNC void __stdcall Arr( const int n1, const int n2, double *x)

{int i;

 for(i=0;i<4;i++)x[i]=i;}// Реально массив скорей всего одномерный, забьем его числами по порядку



В mql4 такой код:

...

#import "Arr.dll"
void Arr(int n1, int n2, double x[]);
#import

...

int start(){

...


double myArray[2][2];

// вычисляем myArray

Arr(n1,n2,myArray);
Alert(myArray[0][0]+" "+myArray[0][1]+" "+myArray[1][0]+" "+myArray[1][1]);// выведем, что получилось в массиве

А вот как грамотно (http://www.find-info.ru/doc/cpp/006/variables-1.htm):

2.16. Как описывать ссылки (указатели) на двумерные массивы? Рассмотрим такую прог-
рамму:
 #include <stdio.h>
 #define First 3
 #define Second 5

 char arr[First][Second] = {
 "ABC.",
 { 'D', 'E', 'F', '?', '\0' },
 { 'G', 'H', 'Z', '!', '\0' }
 };

 char (*ptr)[Second];

 main(){
 int i;

 ptr = arr; /* arr и ptr теперь взаимозаменимы */
 for(i=0; i < First; i++)
 printf("%s\t%s\t%c\n", arr[i], ptr[i], ptr[i][2]);
 }

Указателем здесь является ptr. Отметим, что у него задана размерность по второму
измерению: Second, именно для того, чтобы компилятор мог правильно вычислить двумер-
ные индексы.
 Попробуйте сами объявить

 char (*ptr)[4];
 char (*ptr)[6];
 char **ptr;

и увидеть, к каким невеселым эффектам это приведет (компилятор, кстати, будет
ругаться; но есть вероятность, что он все же странслирует это для вас. Но работать
оно будет плачевно). Попробуйте также использовать ptr[x][y].
 

(Без описания размерности массива в квадратных скобках, причем константой, не переменной, никак не обойтись)

 
Мужики. раз уж вопрос по ДЛЛ...  Как Вы их отлаживаете эти замечательные библиотеки?.. 
 
Laser :
Мужики. раз уж вопрос по ДЛЛ...  Как Вы их отлаживаете эти замечательные библиотеки?.. 


Лично я, или вывожу на экран через sprintf()/MessageBox(), или через запись в файл интересующих меня переменных. Вызов функций библиотеки из MT4.

 
ZombieJesus :
Laser :
Мужики. раз уж вопрос по ДЛЛ...  Как Вы их отлаживаете эти замечательные библиотеки?.. 


Лично я, или вывожу на экран через sprintf()/MessageBox(), или через запись в файл интересующих меня переменных. Вызов функций библиотеки из MT4.

т.е Вы просто можете пронаблюдать как менялось состояние Вашей программы. Так? А приостановить ее выполнение? Изменить значение переменной7

 
Laser :
т.е Вы просто можете пронаблюдать как менялось состояние Вашей программы. Так? А приостановить ее выполнение? Изменить значение переменной7

Мне никогда большего и не требовалось для отладки.

 

Кто-нибудь покажите правильный пример передачи двумерного массива в DLL и обратно при условии что размер массива задаётся внешними параметрами в ЕА.