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

 
gravity001:
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 написана, она по своему, наверно, с типами работает. Хотя числовые типы у меня все работают отлично!!!

Может кто-нибудь знающий приведет примерчик, любой самый простой.


Нет, со строками не проверял. Я просто свои соображения сказал как бы это могло работать. Вообще со строками думаю лучше работать в коде MQL4.

Вот с массивами типа Double работал.
В коде эксперта можешь объявить массив типа
double my_array[MAX_SIZE]
либо
double my_array[];
а в какой нибудь функции эксперта вызвать ArrayResize(my_array, MAX_SIZE);
то есть здесь ты можешь установить размер массива в любом месте эксперта и передать в DLL а в DLL принимаешь его через указатель PDouble
Ну а как с указателями в делфи рабоать и обращаться к нужным элементам я думаю ты знаешь или прочтёшь в хелпе.

Если ты передаёшь массивы по указателю то var писать не надо - ты же элементы массива будешь менять а не сам указатель. Так что ты можешь свободно работать скопией указателя в стеке функции и var писать не надо.
 
Спасибо elritmo. С массивами разабрался. Я, конечно, не понял, что ты имел в виду, когда говорил, что в коде DLL, в Delphi, массив надо обозначить через PDouble.
Я сделал так: вместо array of Double создал тип TArr1Double, вот:
library Ping;

type
    TArr1Double = array of Double;

{$R *.res}

procedure exm1(Arr1Double: TArr1Double); stdcall;
begin
    Arr1Integer[0] := 7.3;
    Arr1Integer[1] := 8.444;
end;

exports
    exm1;

begin
end.
Так у меня все заработало. Причем, такая конструкция
...
procedure exm1(var Arr1Double: TArr1Double); stdcall;
...
выдает критическую ошибку в терминале.

А в MQL4 без разницы (для массива) есть или нету указателя & перед идентификатором. Данные все равно сохраняются. В прочем, как и в других языках программирования. ))
#import "exp.dll"
    void exm1(double & arr1_double[]); // можно и без указателя &.
#import

elritmo проверь пожалуйста, ты так имел ввиду или нет??
Я все прочитал в хелпе и в гугле: PDouble = ^Double - т.е. это только указатель на число Double. Как его использовать для массива я так и не нашел. Может покажешь на примере?

Вот PChar - это указатель на динамический массив. Но для строк PChar пока не понимаю почему не работает.
 
У меня так и с целыми числами работает
...
type
    TArr1Integer = array of Integer;

procedure exm2(Arr1Integer: TArr1Integer); stdcall;
...
 
gravity001:
У меня так и с целыми числами работает
...
type
    TArr1Integer = array of Integer;

procedure exm2(Arr1Integer: TArr1Integer); stdcall;
...




Я даже не пробовал подубные конструкции опасаясь что может моут быть проблемы. Но если у тебя так рабоатет то и я попробую. Вообще то странно передаётся же си массив простой а принимается как делфийский динамический. Ну возможно приведение типа из PDouble к TArrDouble делает всё как надо.
Если так рабоатет то отлично - проверь на стабильность и можешь пользоваться


Если использовал бы PDouble для массива то получилось бы обращенеи к элементам массива так:

library Ping;

{$R *.res}

procedure exm1(Arr1Double: PDouble); stdcall;
begin
Arr1Double^ := 7.3;
Inc(Arr1Double);
Arr1Double^ := 8.444;
end;

exports
exm1;

begin
end.

А товой код что то не правильный ты спутал Arr1Double с Arr1Integer

procedure exm1(Arr1Double: TArr1Double); stdcall;
begin
Arr1Integer[0] := 7.3;
Arr1Integer[1] := 8.444;
end;
 
Вот, тут потыкал и нашел как можно строку передать

DLL на Delphi
...
procedure exm1(str: PChar); stdcall;
begin
    str[0] := 'q';
    str[1] := 'w';
    str[2] := 'e';
    ...
end;
...
Также указатель var нельзя ставить, а то ошибку в терминале выдаст.

Если сделать так
...
procedure exm1(str: PChar); stdcall;
begin
    str := 'qwe';
end;
...
или так
...
procedure exm1(str: PChar); stdcall;
var
    ch: PChar;
begin
    ch[0] := 'q';
    ch[1] := 'w';
    ch[2] := 'e';
    
    str := ch;
end;
...
то строка str не сохраниться! Я также пробовал с массивами. Они тоже по элементно сохраняются.

В MQL4 надо выделить строку достаточной длинны для записи (У меня каракули добавлял в конец строки, если в DLL использоывались индексы, которые выхдят за пределы длинны строки).
...
#import "exp.dll"
void exm1(string str); // указатель & нельзя ставить, а то ошибку терминал выдаст
#import
...

Кто-нибудь может сказать: так корректно переносить строку или возможны ошибки??
 
elritmo:
...
Если ты передаёшь массивы по указателю то var писать не надо - ты же элементы массива будешь менять а не сам указатель. Так что ты можешь свободно работать скопией указателя в стеке функции и var писать не надо.
Да. Я согласен, что var в этом случае не нужен. Я сказал ранее про это, потому что в Delphi, если напишешь var перед массивом и будешь потом функцию в Delphi использовать, то хуже не будет (ошибок не будет). А вот, если так напишешь в DLL и будешь импортировать функцию в MQL4, то терминал выдаст критическую ошибку!!
 
А вот так что не работает:

procedure exm1(str: PChar); stdcall;
begin
   StrSpy(str, 'qwe');
end;

str должна в MQL быть проинициализирована вот так
for(i = 0; i < 4; i++) str = str + " ";
 
elritmo писал (а):
...
А товой код что то не правильный ты спутал Arr1Double с Arr1Integer

procedure exm1(Arr1Double: TArr1Double); stdcall;
begin
Arr1Integer[0] := 7.3;
Arr1Integer[1] := 8.444;
end;
...
Да. Здесь я попутал. Надо писать Arr1Double;
 
elritmo:
...
Если использовал бы PDouble для массива то получилось бы обращенеи к элементам массива так:

library Ping;

procedure exm1(Arr1Double: PDouble); stdcall;
begin
Arr1Double^ := 7.3;
Inc(Arr1Double);
Arr1Double^ := 8.444;
end;
...
Спасибо. Узнал новое для себя. Все нормально работает.
У меня так и с PInteger, тоже работает, сам проверил!
 
>> Пробовал со строкой, как ты написал
Ну и как работает или нет?