Массив из\в delphi

Программирование на Visual Basic, главный форум. Обсуждение тем программирования на VB 1—6.
Даже если вы плохо разбираетесь в VB и программировании вообще — тут вам помогут. В разумных пределах, конечно.
Правила форума
Темы, в которых будет сначала написано «что нужно сделать», а затем просьба «помогите», будут закрыты.
Читайте требования к создаваемым темам.
ACiD
Бывалый
Бывалый
Аватара пользователя
 
Сообщения: 261
Зарегистрирован: 10.12.2005 (Сб) 2:29
Откуда: г. Санкт - Петербург

Массив из\в delphi

Сообщение ACiD » 04.05.2007 (Пт) 21:48

Доброго времени суток!
Не могу решить задачку.
Пишу Длл-ку на Delphi:
...
Код: Выделить всё
type
MyArrN=array[0..4] of byte;
procedure Proba(var mass:MyArrN);stdcall;
var j:byte;
begin
for j:=0 to 4 do messagedlg(inttostr(j)+'  '+inttostr(mass[j]),mtInformation, [mbOk], 0);
   //выдаются числа не соответствующие реальности :(
for j:=0 to 4 do mass[j]:=10;
   //переменная вроде var, а передаваться не хочет :(
end;
exports Proba;

...

Объявляю её в VB:
Код: Выделить всё
Private Declare Sub Proba Lib "d:\prj.dll" (ByRef mass() As Byte)
...
Dim mm(5) As Byte
For j = 0 To 5: mm(j) = j: Next [j]
Proba mm
For j = 0 To 5: MsgBox Str(j) & "  " & Str(mm(j)), vbInformation, "Привет от VB": Next [j]


при передаче массив приобретает неожиданные значения,
при возврате ничего не изменяется

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16478
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Сообщение Хакер » 04.05.2007 (Пт) 21:59

>>выдаются числа не соответствующие реальности

Скорее всего - это "куски" указателя.

Попробуй объявлять функцию так:

Private Declare Sub Proba Lib "d:\prj.dll" (Byval pArray as long)

и передавать VarPtr(mm(0))

Хотя, я не знаю как дельфи поступет с параметрами. Вот если бы С...

И, кстати, почему у тебя в VB-шной части 6 байт, а в дельфийной - 4?
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

GSerg
Шаман
Шаман
 
Сообщения: 14286
Зарегистрирован: 14.12.2002 (Сб) 5:25
Откуда: Магадан

Сообщение GSerg » 04.05.2007 (Пт) 22:02

Не смущает, ACiDXX, что ровно об этом же спрошено в топике, который даже не успел уйти с первой страницы?

http://bbs.vbstreets.ru/viewtopic.php?p=6659940#6659940
Как только вы переберёте все варианты решения и не найдёте нужного, тут же обнаружится решение, простое и очевидное для всех, кроме вас

tyomitch
Пользователь #1352
Пользователь #1352
Аватара пользователя
 
Сообщения: 12822
Зарегистрирован: 20.10.2002 (Вс) 17:02
Откуда: חיפה

Сообщение tyomitch » 04.05.2007 (Пт) 23:59

Хакер, в дельфийской пять байт.


При передаче "ByRef mass() As Byte" передаётся адрес SAFEARRAY. А дельфийская сторона ожидает получить адрес первого байта. Значит, нужно передавать "ByRef mass As Byte".
Изображение

ACiD
Бывалый
Бывалый
Аватара пользователя
 
Сообщения: 261
Зарегистрирован: 10.12.2005 (Сб) 2:29
Откуда: г. Санкт - Петербург

Сообщение ACiD » 04.05.2007 (Пт) 23:59

спасибо всем кто ответил.
Отдельная благодарность Тёмычу, как всегда на высоте!

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16478
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Сообщение Хакер » 05.05.2007 (Сб) 0:14

tyomitch
И действительно 5. Но в VB-шном - 6.

При передаче "ByRef mass() As Byte" передаётся адрес SAFEARRAY.


Не надо мне этого рассказывать :) Это я знаю :)

А дельфийская сторона ожидает получить адрес первого байта.


В этом я и сомневался. Но раз так - мой способ правильный.

Значит, нужно передавать "ByRef mass As Byte".

Тоже можно.
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

tyomitch
Пользователь #1352
Пользователь #1352
Аватара пользователя
 
Сообщения: 12822
Зарегистрирован: 20.10.2002 (Вс) 17:02
Откуда: חיפה

Сообщение tyomitch » 05.05.2007 (Сб) 10:18

Хакер писал(а):
При передаче "ByRef mass() As Byte" передаётся адрес SAFEARRAY.


Не надо мне этого рассказывать :) Это я знаю :)

Впервые вижу, чтобы SAFEARRAY называли "кусками указателя".

Хакер писал(а):
А дельфийская сторона ожидает получить адрес первого байта.


В этом я и сомневался. Но раз так - мой способ правильный.

Значит, нужно передавать "ByRef mass As Byte".

Тоже можно.

И это во-первых, проще (не нужен VarPtr), а во-вторых, с контролем типов.
Хотя какое дело PHP-гуру до контроля типов, верно? ;-)
И вообще, есть только пять истинных типов данных :twisted: :twisted:
Изображение

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16478
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Сообщение Хакер » 05.05.2007 (Сб) 10:40

tyomitch писал(а):Впервые вижу, чтобы SAFEARRAY называли "кусками указателя".

а теперь смотри: ты сам писал:
tyomitch писал(а):При передаче "ByRef mass() As Byte" передаётся адрес SAFEARRAY


Адрес SAFEARRAY - или другими словами - указатель на SAFEARRAY.

Указатель это DWORD - т.е. 4 байта.

Значит в mass[0], mass[1], mass[2], mass[3] - лежат куски (отдельные байты), этого DWORD-адреса SAFEARRAY.

Ну и в чём я тогда не прав?? :roll:


tyomitch писал(а):И это во-первых, проще, а во-вторых, с контролем типов.
Хотя какое дело PHP-гуру до контроля типов, верно? ;-)

Нет, не верно. Мой вариант более универсальный. Ибо я могу передать указатель хоть на что (хоть StrPtr(StrConv(...)) ) - а дельфийная функция мне это обработает.

И причём тут PHP-гуру :roll: ?


tyomitch писал(а):И вообще, есть только пять истинных типов данных :twisted: :twisted:

Я спорил?
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

tyomitch
Пользователь #1352
Пользователь #1352
Аватара пользователя
 
Сообщения: 12822
Зарегистрирован: 20.10.2002 (Вс) 17:02
Откуда: חיפה

Сообщение tyomitch » 05.05.2007 (Сб) 11:48

Хакер писал(а):
tyomitch писал(а):Впервые вижу, чтобы SAFEARRAY называли "кусками указателя".

а теперь смотри: ты сам писал:
tyomitch писал(а):При передаче "ByRef mass() As Byte" передаётся адрес SAFEARRAY


Адрес SAFEARRAY - или другими словами - указатель на SAFEARRAY.

Указатель это DWORD - т.е. 4 байта.

Значит в mass[0], mass[1], mass[2], mass[3] - лежат куски (отдельные байты), этого DWORD-адреса SAFEARRAY.

Ну и в чём я тогда не прав?? :roll:

Хакер, передаётся адрес SAFEARRAY. Принимается адрес первого байта. В массиве оказывается сам этот SAFEARRAY, порезанный на байты.


Хакер писал(а):
tyomitch писал(а):И это во-первых, проще, а во-вторых, с контролем типов.
Хотя какое дело PHP-гуру до контроля типов, верно? ;-)

Нет, не верно. Мой вариант более универсальный. Ибо я могу передать указатель хоть на что (хоть StrPtr(StrConv(...)) ) - а дельфийная функция мне это обработает.

Действительно, зачем вообще нужен контроль типов?
Долой! Даёшь единый скалярный тип, как в PHP! Даёшь универсальность!


Хакер писал(а):
tyomitch писал(а):И вообще, есть только пять истинных типов данных :twisted: :twisted:

Я спорил?

Да нет, я просто вспомнил предыдущего борца с типизацией. :-D
Изображение

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16478
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Сообщение Хакер » 05.05.2007 (Сб) 12:31

tyomitch писал(а):Хакер, передаётся адрес SAFEARRAY.


Да.

tyomitch писал(а):Принимается адрес первого байта. В массиве оказывается сам этот SAFEARRAY, порезанный на байты.


Даа? Т.е. дельфи берут из стека адрес{1}, и копируют 5 байт памяти из того места, на которой указывае этот адрес{1} и в то место, где лежит первый элемент дельфишного байтвого массива? Тогда да, тогда там не куски указателя, а куски структуры.




tyomitch писал(а):Действительно, зачем вообще нужен контроль типов?
Долой! Даёшь единый скалярный тип, как в PHP! Даёшь универсальность!


Почему PHP ? :x
А что Perl, VBScript, JavaScript лишены мульти-типности?
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

tyomitch
Пользователь #1352
Пользователь #1352
Аватара пользователя
 
Сообщения: 12822
Зарегистрирован: 20.10.2002 (Вс) 17:02
Откуда: חיפה

Сообщение tyomitch » 05.05.2007 (Сб) 14:36

Делфи ничего не копируют.
Они берут из стека адрес, и прибавляют к нему смещение при индексации. Как и Си.

-----

Бестиповых языков много. Но VB6 к ним не относится. И поэтому не нужно грубой силой делать из него бестиповый язык. "Шуруп, забитый молотком, держится крепче, чем гвоздь, закрученный отвёрткой" (c)
Изображение

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16478
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Сообщение Хакер » 05.05.2007 (Сб) 15:18

tyomitch писал(а):Делфи ничего не копируют.
Они берут из стека адрес, и прибавляют к нему смещение при индексации.

Т.е. ты хочешь сказать, если мы в дельфийной функции напишем
mass[i] = 0; в цикле, мы затрём SAFEARRAY нулями ?

(разумеется при том коде, который изначально предлагал автор)
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

tyomitch
Пользователь #1352
Пользователь #1352
Аватара пользователя
 
Сообщения: 12822
Зарегистрирован: 20.10.2002 (Вс) 17:02
Откуда: חיפה

Сообщение tyomitch » 05.05.2007 (Сб) 15:41

Угу, хочу.
Изображение

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16478
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Сообщение Хакер » 05.05.2007 (Сб) 15:59

В си ничего не затрётся.

Сишная функция
Код: Выделить всё
INT APIENTRY Test(INT t)
{
    t = 1234;
    return 0;
}


Не будет менять значение переменной, переданной ByRef, пока t не заменишь на *t .

Принимается адрес первого байта

В дельфях по-умолчанию используется передача по ссылке?
Или дельфи ожидают адрес первого байта конкретно в случае - если аргумент функции имеет user-defined тип с массивом внутри?
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

GSerg
Шаман
Шаман
 
Сообщения: 14286
Зарегистрирован: 14.12.2002 (Сб) 5:25
Откуда: Магадан

Сообщение GSerg » 05.05.2007 (Сб) 16:04

Хакер писал(а):В дельфях по-умолчанию используется передача по ссылке?

В дельфях по умолчанию передача по значению.
Но у параметра стоит модификатор var, что равносильно нашему byref...
Как только вы переберёте все варианты решения и не найдёте нужного, тут же обнаружится решение, простое и очевидное для всех, кроме вас

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16478
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Сообщение Хакер » 05.05.2007 (Сб) 16:09

Спасибо, теперь всё ясно.
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

ACiD
Бывалый
Бывалый
Аватара пользователя
 
Сообщения: 261
Зарегистрирован: 10.12.2005 (Сб) 2:29
Откуда: г. Санкт - Петербург

Сообщение ACiD » 14.05.2007 (Пн) 10:59

По этой теме возникла ещё одна проблемка:
массив с типизированными данными работает нормально,
но когда добавляю тип string(=widestring) VB почему-то
начинает вылетать.

Код: Выделить всё
type
Tproba=record c:widestring; end;
myarr=array[0..5] of Tproba;
myarr2=array[0..5] of widestring;
{$R *.res}
procedure modyf(var mass:myarr);stdcall;var i:byte;
begin for i:=0 to 5 do mass[i].c:='proba'+IntToStr(i);end;

procedure modyf2(var mass:myarr2);stdcall;var i:byte;
begin for i:=0 to 5 do mass[i]:='proba'+IntToStr(i);end;
exports modyf,modyf2;
Вложения
dll.rar
(39.03 Кб) Скачиваний: 162

tyomitch
Пользователь #1352
Пользователь #1352
Аватара пользователя
 
Сообщения: 12822
Зарегистрирован: 20.10.2002 (Вс) 17:02
Откуда: חיפה

Сообщение tyomitch » 14.05.2007 (Пн) 11:09

Код со стороны VB тоже покажи.
Изображение

ACiD
Бывалый
Бывалый
Аватара пользователя
 
Сообщения: 261
Зарегистрирован: 10.12.2005 (Сб) 2:29
Откуда: г. Санкт - Петербург

Сообщение ACiD » 14.05.2007 (Пн) 11:52

Код: Выделить всё
Dim a(5) As Tproba
modyf a(0)
' или так
Dim a(5) As String
modyf2 a(0)

tyomitch
Пользователь #1352
Пользователь #1352
Аватара пользователя
 
Сообщения: 12822
Зарегистрирован: 20.10.2002 (Вс) 17:02
Откуда: חיפה

Сообщение tyomitch » 14.05.2007 (Пн) 11:56

А декларации?
Изображение

ACiD
Бывалый
Бывалый
Аватара пользователя
 
Сообщения: 261
Зарегистрирован: 10.12.2005 (Сб) 2:29
Откуда: г. Санкт - Петербург

Сообщение ACiD » 14.05.2007 (Пн) 11:58

Код: Выделить всё
Private Declare Sub modyf Lib "dll.dll" (ByRef mass As Tproba)
Private Declare Sub modyf2 Lib "dll.dll" (ByRef mass As String)
Private Type Tproba
c As String
End Type

tyomitch
Пользователь #1352
Пользователь #1352
Аватара пользователя
 
Сообщения: 12822
Зарегистрирован: 20.10.2002 (Вс) 17:02
Откуда: חיפה

Сообщение tyomitch » 14.05.2007 (Пн) 12:12

Значит, вот теперь пригодится совет Хакера объявить параметр как ByVal As Long, и передавать VarPtr(a(0)).

Когда в декларации прописан String или UDT со String-ом внутри, VB при передаче делает ненужные конверсии в ANSI и обратно.
Изображение

ACiD
Бывалый
Бывалый
Аватара пользователя
 
Сообщения: 261
Зарегистрирован: 10.12.2005 (Сб) 2:29
Откуда: г. Санкт - Петербург

Сообщение ACiD » 14.05.2007 (Пн) 12:30

Тёмыч, ну просто спаситель!
Хакеру тоже спасибо.
Вот только одного понять не могу
почему изменяются данные? Там же ByVal.

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16478
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Сообщение Хакер » 14.05.2007 (Пн) 12:41

Данные изменяются, потому что их изменяет Дельфийная функция.

Гениально, правда?
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.


Вернуться в Visual Basic 1–6

Кто сейчас на конференции

Сейчас этот форум просматривают: Google-бот и гости: 34

    TopList