Возврат строки из DLL - страница 4

 

Она пашет даже в такой конструкции

string s1 = SQLGETstring( sss );

т.е. без предварительной разметки s1.

Это надо осмыслить. Беру тайм аут

 
lusp:
YuraZ:
lusp:
зачастую ... от среды обитания "питомцев" - программ, много зависит

ОК, давайте. Адрес в профиле

не т адреса ловите тут

Действительно пашет !

А что такое в вашей функции

spar[0]='1';


для чего это надо ?

это ошметок :-) просто сначала сделал тупо изменение переданной строки а потом сверху залил строкой ПРОВЕРКА

 
lusp:

Она пашет даже в такой конструкции

string s1 = SQLGETstring( sss );

т.е. без предварительной разметки s1.

Это надо осмыслить. Беру тайм аут

это просто потому что по чистой случайности ЭТОТ кусок памяти где живет s1

ничему не мешает



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

 

Опыты продолжаются

Сделал так:

function test(par1, par2 : PChar):PChar; export; stdcall;
begin
  try
    if length(string(Par1) + '-->' + string(Par2)) < 250 then
      Result :=  PChar(string(Par1) + '-->' + string(Par2) + #0)
    else raise Exception.Create('Length of string  too big (' +
     intToStr(length(string(Par1) + '-->' + string(Par2))) + ')' + #0);
  except
    on e:Exception do
    begin
      Result :=  PChar('Test error: ' + e.Message + #0);
    end;
  end;
end;

Работает нормально. Но при выходе из MT4 получаем трабл

There has been a critical error
Time        : 2008.05.26 11:04
Program     : Client Terminal
Version     : 4.00 (build: 216, 16 Apr 2008)
OS          : Windows 2000 Professional 5.0 Service Pack 4 (Build 2195)
Processors  : 1 x X86 (level 15)
Memory      : 523760/333900 kb
Exception   : C0000005
Address     : 00000000
Access Type : read
Access Addr : 00000000

Registers   : EAX=0017E6CC CS=3794c78 EIP=0017E640 EFLGS=7FFDF000
            : EBX=0017E640 SS=179b320 ESP=0012F344 EBP=0017E67C
            : ECX=00000000 DS=131ea4 ESI=00131EAC FS=77fcfcc8
            : EDX=0017E67C ES=17e6e8 EDI=0017E6F0 GS=77fcfcc8

Stack Trace : 0017E6CC 0017E67C 0012F3B0 0017E6CC
            : 0017E67C 0012F3B0 0017E6CC 0017E67C
            : 0012F3B0 0017E6CC 0017E67C 0012F3B0
            : 0017E6CC 0017E67C 0012F3B0 0017E6CC

Modules     :
          1 : 00400000 002A9000 d:\program files\metatrader 4\terminal.exe
          2 : 032E0000 00013000 d:\winnt\system32\iphlpapi.dll
          3 : 03300000 00017000 d:\winnt\system32\mprapi.dll
          4 : 03620000 00019000 d:\winnt\system32\dhcpcsvc.dll
          5 : 03790000 0000B000 d:\program files\borland\delphi7\bin\borlndmm.dll
          6 : 10000000 00019000 d:\program files\bonjour\mdnsnsp.dll
          7 : 6B1E0000 00005000 d:\winnt\system32\msimg32.dll
          8 : 6C120000 0000E000 d:\winnt\system32\mfc42loc.dll
          9 : 6C290000 000FB000 d:\winnt\system32\mfc42.dll
         10 : 71710000 00084000 d:\winnt\system32\comctl32.dll
         11 : 74F60000 0001E000 d:\winnt\system32\msafd.dll
         12 : 74FA0000 00007000 d:\winnt\system32\wshtcpip.dll
         13 : 74FB0000 00008000 d:\winnt\system32\ws2help.dll
         14 : 74FC0000 00014000 d:\winnt\system32\ws2_32.dll
         15 : 74FE0000 00009000 d:\winnt\system32\wsock32.dll
         16 : 750E0000 00010000 d:\winnt\system32\samlib.dll
         17 : 75150000 00006000 d:\winnt\system32\netrap.dll
         18 : 76AE0000 0003E000 d:\winnt\system32\comdlg32.dll
         19 : 770F0000 0006F000 d:\winnt\system32\rpcrt4.dll
         20 : 772C0000 00066000 d:\winnt\system32\shlwapi.dll
         21 : 77330000 00023000 d:\winnt\system32\adsldpc.dll
         22 : 77360000 00030000 d:\winnt\system32\activeds.dll
         23 : 77470000 00011000 d:\winnt\system32\rasman.dll
         24 : 77490000 00034000 d:\winnt\system32\rasapi32.dll
         25 : 774D0000 00005000 d:\winnt\system32\icmp.dll
         46 : 7CD10000 00050000 d:\winnt\system32\netapi32.dll
         47 : 7CD70000 000EF000 d:\winnt\system32\ole32.dll
         48 : 7CE80000 00247000 d:\winnt\system32\shell32.dll

Call stack  :
И непонятно почему.
 
lusp:

Опыты продолжаются

Сделал так:

function test(par1, par2 : PChar):PChar; export; stdcall;
begin
  try
    if length(string(Par1) + '-->' + string(Par2)) < 250 then
      Result :=  PChar(string(Par1) + '-->' + string(Par2) + #0)
    else raise Exception.Create('Length of string  too big (' +
     intToStr(length(string(Par1) + '-->' + string(Par2))) + ')' + #0);
  except
    on e:Exception do
    begin
      Result :=  PChar('Test error: ' + e.Message + #0);
    end;
  end;
end;
И непонятно почему.

нельзя создать - выделить память в DLL и вернуть это наверх

Память под строку должна - создаваться - выделяться в MT4

фактически вы только передаете адрес строки (в DLL), которую выделил MT4

и манипулируете этим массивом уже в DLL

 

Наконец то получен вариант который меня устроил. Итак DLL

function test(par1: PChar; Res: PChar):PChar; export; stdcall;
var n : Integer;
begin
  n := StrLen(Res);
  test := StrPLCopy(Res, IntToStr(n) + ' = ' + string(par1) + ' - 3456789012345678901234567890123456789012345678901234567890',n);
end;

в переменной n имеем максимальную длину строки результата, которая была размечена в советнике

функция StrPLCopy следит за тем, что бы мы не дай бог не записали в результат строку длиннее разметки

При этом рекомендуемый от Borland менеджер разделяемой памяти должен быть отключен. Если его включить получаем стабильный трабл при закрытии MT4

Описание функции в советнике выглядит так

#import "TestDll.dll" 
  string test(string s1, string );

А собственно вызов так

int start() {
    if (!(IsOptimization() || IsTesting())) {
      string  s1 = "1234567890012345678901234567890";  //
      string sss = "0987654321098765432109876543210";  //
      s1 = test(Symbol(), sss );
      Print("s1=",s1,"    sss=",sss);
   }  
  return(0);
}

При этом получаем

16:45:06 DllTest GBPCHF,H1: s1=31 = GBPCHF - 34567890123456789    sss=31 = GBPCHF - 34567890123456789
16:45:08 DllTest GBPCAD,H1: s1=31 = GBPCAD - 34567890123456789    sss=31 = GBPCAD - 34567890123456789
16:45:09 DllTest GBPCAD,H1: s1=31 = GBPCAD - 34567890123456789    sss=31 = GBPCAD - 34567890123456789
16:45:09 DllTest EURCAD,H1: s1=31 = EURCAD - 34567890123456789    sss=31 = EURCAD - 34567890123456789
16:45:09 DllTest CADCHF,H1: s1=31 = CADCHF - 34567890123456789    sss=31 = CADCHF - 34567890123456789

Как видно, длина возвращенной строки ограничена разметкой.

И никакого мусора ...

 
lusp:

Наконец то получен вариант который меня устроил. Итак DLL


И никакого мусора ...

:-)

 

Всем доброго времени суток!!!

Вопрос к разработчикам

Уважаемые разработчики, подскажите пожалуйста как можно загружать в стороннюю dll массивы произвольной размерности, а именнь одно, двух и более размерностей.

Заранее благодарен за ответы.

С наилучшими пожеланиями Debugger/



 
lusp:

Наконец то получен вариант который меня устроил. Итак DLL

в переменной n имеем максимальную длину строки результата, которая была размечена в советнике

функция StrPLCopy следит за тем, что бы мы не дай бог не записали в результат строку длиннее разметки

При этом рекомендуемый от Borland менеджер разделяемой памяти должен быть отключен. Если его включить получаем стабильный трабл при закрытии MT4

Описание функции в советнике выглядит так

А собственно вызов так

При этом получаем

Как видно, длина возвращенной строки ограничена разметкой.

И никакого мусора ...

У меня похожая ситуация. Код DLL на С:
MT4_EXPFUNC int __stdcall GetStringA( char* retn_str )
{
        int retn = false;

        if( retn_str != NULL )
        {
                strcpy( retn_str, "1111" );
                retn = true;
        }

        return retn;
}

MT4_EXPFUNC int __stdcall GetStringB( char* retn_str )
{
        int retn = false;

        if( retn_str != NULL )
        {
                strcpy( retn_str, "2222" );
                retn = true;
        }

        return retn;
}
Код на mql:
string s1 = "dddddddddddddddddddd", s2 = "dddddddddddddddddddd";
GetStringA(s1);
GetStringB(s2);
Print("s1 = ", s1, " s2 = ", s2);
Вывод такой:
str_from_dll EURUSD,H1: s1 = 2222 s2 = 2222
Если переменные инициализируем различными строками:
string s1 = "dddddddddddddddddddd", s2 = "1ddddddddddddddddddd";
То в журнале пишет правильно:
str_from_dll EURUSD,H1: s1 = 1111 s2 = 2222
Видимо указатель строки с одинаковым значением хранит в одной области памяти. Интересно, это так задумано в пуле строк?
 
Строкам- которые- буфера-для длль одинаковое значение задавать нельзя. 
https://www.mql5.com/ru/forum/120200
Причина обращения: