Импорт фунций из DLL. Строковые перепенные и массивы!

 
Хочу импортировать такую функцию из DLL (исходный код DLL написан на Delphi):
library Ping;

function sum(const str1: PChar; var str2: PChar): PChar; stdcall;
begin
  Result := PChar( string( str1 ) + string( str2 ) );
  str2 := 'qwert';
end;

exports
  sum;

begin
end.

PChar = PAnsiChar - это по умолчанию.

Для этого пишу в коде советника следующее
#import "ping.dll"
      string sum(string str1, string & str2);
#import
И когда функция вызываеться, то проиисходит критическая ошибка и терминал вылетает.

Если убрать знак & перед str2
#import "ping.dll"
      string sum(string str1, string str2);
#import
то, тогда результат есть, но str2 не меняет своего значения. А надо, что бы оно его изменило.

Еще хотел str2 представить в виде масива целых чисел и перенести, Вот так примерно
library Ping;

function sum(const str1: array of Integer; var str2: array of Integer): Integer; stdcall;
var
  I: Integer;
begin
  for I := 0 to 10 do
    str2[I] := I;        // эта запись толко как пример
  Result := 0;
end;

exports
  sum;

begin
end.

Но массив тоже не получилось изменить пишет ошибку и вылетает.

Пробывал сделать по разному, но получить измененую переменную str2 так и не получилось.
Иногда в ней в str2 непонятные значки записывались.
Вобщем, искал решение проблемы на форуме, но так и не нашел.
Напишите, пожалуйста, пример того как можно получить измененные параметры функции, конкретно строковые и массивы, остальные работают.

Хотелось бы, чтобы в документации про это написалибы побольше.
 
Что-то не помню я, чтобы в Делфи значение по ссылке передавались с синтаксисом на сях. А в примере с массивом вообще без ссылок передается, поэтому ничего и не возвращается.
 
Выдели строку заданной длинныв эксперте на MQL и в неё уже записывай строку в DLL по указателю PChar.
Так же ты НЕ сможешь принимать в DLL как динамический массив str1: array of Integer. Возможно либо так str1: PInteger, либо str1: PDouble
Массивы в коде эксперта на MQL объявляешь либо заданной длинны либо изменением размера массива ArrayResize до нужного значения.
Память не выделяй для массивов в DLL указатель на которые хочешь передать в эксперт. Создание и задание размера массива следует
производить в тексе MQL эксперта.
Обмениваться массивами данных желательно через указатель (в эксперте это double[] либо double&[]). Я в эксперте привожу Integer к элементам Double массива, а  в DLL наоборот элемены массива Double к Interger так же можно и с Char. Вероятно можно и массивы Integer передавать но у меня не получалось что то.
 
favoritefx:
Что-то не помню я, чтобы в Делфи значение по ссылке передавались с синтаксисом на сях. А в примере с массивом вообще без ссылок передается, поэтому ничего и не возвращается.


Извини, но я не понял, как ДИНАМЧЕСКИЙ массив без ссылки передается.  Вообщем, мне важно передать массив. Если не сложно напиши пример. Я пойму.
 
elritmo:
Выдели строку заданной длинны в эксперте на MQL и в неё уже записывай строку в DLL по указателю PChar.


Как можно выделить строку заданной длинны? Я так делал
string a = "";
string b = "12345";
Если я правильно понял, то после этого: строка a имеет длинну 0, а строка b имеет длинну 5.
В DDL ничего не менял, там у меня строка str2 := 'qwert' имеет длинну 5, как и строка b.
library Ping;

function sum(const str1: PChar; var str2: PChar): PChar; stdcall;
begin
Result := PChar( string( str1 ) + string( str2 ) );
str2 := 'qwert';
end;

exports
sum;

begin
end.
Но ничего не поменялось. Так же, в такой конструкции (без указателя &)
#import "ping.dll"
      string sum(string str1, string str2);
#import
Строка str2 возвращает кривые символы. Функция возвращает нормальное значение.
А в конструкции (с указателем &)
#import "ping.dll"
      string sum(string str1, string & str2);
#import
Терминал, также выдает критическую ошибку и вылетает. По спавке и по логике указатель & не надо ставить. А что делать, если не работает.
Может я не правильно код в Delphi пишу или направильно DLL создаю.

Ещё пробовал так
string b;
ArrayResize(b, 5);
Но так ошибку пишет и ArrayResize(b, 5) возвращает -1 (ошибка № 4065). В MQL4 string так длинну не меняет.

Может кто-нибудь из модераторов происнит по конкретнее как должно быть или, хотя бы, как у них тип string работает. А то ссылка на строку есть, а размера строки нет. Мне кажется из за размера все проблеммы.
 
elritmo:
...
Так же ты НЕ сможешь принимать в DLL как динамический массив str1: array of Integer. Возможно либо так str1: PInteger, либо str1: PDouble
...
После замены
str1: array of Integer на str1: PDouble
Терминал перестал выдавть критическую ошибку и все заработало.  Но вот вопрос как я с таким типом PDouble
буду с массивом работать и ещё надо его изменить. Я не знаю, расскажи.

...
Массивы в коде эксперта на MQL объявляешь либо заданной длинны либо изменением размера массива ArrayResize до нужного значения.
...
Вот так делал
 
  double a[2] = {1, 2};
  double b[2] = {3, 4};
Вроде, правильно.

...
Память не выделяй для массивов в DLL указатель на которые хочешь передать в эксперт. Создание и задание размера массива следует
производить в тексе MQL эксперта.
...
Я так и делаю.

...
Обмениваться массивами данных желательно через указатель (в эксперте это double[] либо double&[])...
#import "ping.dll"
     double sum(double a[], double & b[]);
#import
Ещё хочу уточнить. Если я хочу массив изменить в DLL и сохранить его измененным после выполнения функции, то указатель & нужен ИЛИ нет?
В справке есть пример и там он стоит.
Вот пример из справки
Справочник MQL4 - Основы языка - Препроцессор - Импорт функций

#import "ExpertSample.dll"
   int    GetIntValue(int);
   double GetDoubleValue(double);
   string GetStringValue(string);
   double GetArrayItemValue(double arr[], int, int);
   bool   SetArrayItemValue(double& arr[], int,int, double);
   double GetRatesItemValue(double rates[][6], int, int, int);
   int    SortStringArray(string& arr[], int);
   int    ProcessStringArray(string& arr[], int);
#import

У меня если после string ставить указатель &, то всегда происходит критическая ошибка. Что будет в таком случае "double& arr[]" даже не знаю, потому что с массивами вообще не получается работать.  Но хотелось бы узнать.

Может у меня терминал ошибочный или даже в справке не правильно написано???
 
Ещё забыл сказать. Если пишите "истину", то не поленитесь примерчик написать или отрывки кода (как на MQL4 так и на языке, на котором DLL написана). Вот.
Пожалуйста. :)
 
Попробуй вот так сделать

MQL4 код

#import "ping.dll"
  void sum(string str1, string str2, string res_str);
#import

string
void init() {
  str1 = "string1 "; str2 = "string2";
  for(int i = 0; i < MAX_LENGTH; i++)  // Длина  MAX_LENGTH должна быть больше либо равна суммарной длине str1 и str2
     res_str = res_str + " ";
  sum(str1, str2, res_str);
}

Dll код

library Ping;

procedure sum(str1, str2, res_str : PChar); stdcall;
begin
  StrCpy(res_str, PChar( string( str1 ) + string( str2 ) );
  Суть в том что мт4 уже передал res_str - массива char с нулём на конце длиной MAX_LENGTH и тебе надо просто скопировать все элементы -
  результат сложения string( str1 ) + string( str2 ) в эту строку не создавая новой. То есть теперь вместо некоторых пробелов будет строка - результат сложения.
end;

exports
sum;

begin
end

Есть ещё метод - ты в функции sum выделяешь память для строки и возвращаешь PChar а в MQL4 советнике присваиваешь результатsum переменной типа string. Затем в deinit вызываешь Dll функцию которой передаёшь этот эту пеерменную стринг на удаление. То есть в длл произойдёт удаление массива по переданному указателю на эту строку.
 
elritmo:
Попробуй вот так сделать
...
Попробовал (. Все по прежнему.

Сделал все как ты написал. В результате переменная res_str не изменилась (как была из пробелов так и осталась).

Еще в твоем коде
Dll код

library Ping;

procedure sum(str1, str2, res_str : PChar); stdcall;
...
Переменная res_str не обозначена как var, (т.е. чтобы она сохранила свое значение после вызова функции надо обязательно писать вар перед ее объявлением, в Delphi это точно).
Я сначало твой вариант попробывал и потом еще исправил так
Dll код

library Ping;

procedure sum(str1, str2: PChar; var res_str : PChar); stdcall;
и попробывал. Но ни в первом ни во втором случае не получается. Максимум что получил - это каракули.

А у тебя этот пример работает или ты не проверял???
Может я кривой.

Я думаю проблема в моей DLL, так как она на Delphi написана, она по своему, наверно, с типами работает. Хотя числовые типы у меня все работают отлично!!!

Может кто-нибудь знающий приведет примерчик, любой самый простой.
 
elritmo:
Попробуй вот так сделать
...
А на счет массивов не подскажешь как быть. Также примерчиком.
 
А вообще, кто-нибудь из модераторов или из разрабодчиков мне ответит, или мне надо письмо в тех. поддержку писать?