Visual Basic, .NET, ASP, VBScript
 

   
   
     

Форум - Общий форум

Страница: 1 | 2 | 3 |

 

  Вопрос: Опять указатели и CopyMemory Добавлено: 20.03.05 19:22  

Автор вопроса:  Neco | Web-сайт: neco.pisem.net | ICQ: 247906854 
Есть функция
EXPORT char* _stdcall exGetAddrToRead()
{
return AddrToRead;
}
В VB обявлена:
Private Declare Function exContinueRecord Lib "AudioRead" () As Long

теперь мне надо этот указатель на массив передать в другую библиотеку (тоже мою), но напрямую нельзя, тока через VB.
Я делаю так:

        Dim tmp() As Byte
        ReDim tmp(sz-1)
        CopyMemory tmp(0), ByVal exGetAddrToRead , sz
        exAddThisToWrite VarPtr(tmp(0)), sz

где функция exAddThisToWrite объявлена так:
Private Declare Function exAddThisToWrite Lib "AudioWrite" (ByVal refArr As Any, ByVal lenArr As Long) As Long

Так вот в результате всех этих операций у меня в звуке (массив это звук) появляются помехи то ли на конце то ли в начале. Но почему-то если сделать напрямую:
exAddThisToWrite addr, sz
то всё пашет на Ура.
А массив мне нужен - без него никак.

Ответить

  Ответы Всего ответов: 31  

Номер ответа: 1
Автор ответа:
 CyRax



Разработчик Offline Client

ICQ: 204447456 

Вопросов: 180
Ответов: 4229
 Web-сайт: basicproduction.nm.ru
 Профиль | | #1
Добавлено: 20.03.05 19:42
Никакой разницы между VarPtr(tmp(0)) и addr нет.

Ответить

Номер ответа: 2
Автор ответа:
 CyRax



Разработчик Offline Client

ICQ: 204447456 

Вопросов: 180
Ответов: 4229
 Web-сайт: basicproduction.nm.ru
 Профиль | | #2
Добавлено: 20.03.05 19:43
Что такое addr? Тоже самое что и exGetAddrToRead?

Ответить

Номер ответа: 3
Автор ответа:
 CyRax



Разработчик Offline Client

ICQ: 204447456 

Вопросов: 180
Ответов: 4229
 Web-сайт: basicproduction.nm.ru
 Профиль | | #3
Добавлено: 20.03.05 19:47
И вообще, что ты туда передаёшь?
 Попробуй ReDim tmp(sz).

Ответить

Номер ответа: 4
Автор ответа:
 cresta



Вопросов: 117
Ответов: 1538
 Профиль | | #4 Добавлено: 20.03.05 20:46
Судя по тому, что массив копируется во временный буфер, значит он обрабатывается в VB проге.

Помехи надо искать там, где обрабатываешь массив, а CopyMemory ни при чём здесь. Она не может изменить содержимое ячеек при копировании.
Потому и работает без искажений, когда напрямую передаешь.

А если ты не обрабатываешь массив, то и копировать его незачем.

Ответить

Номер ответа: 5
Автор ответа:
 Neco



ICQ: 247906854 

Вопросов: 133
Ответов: 882
 Web-сайт: neco.pisem.net
 Профиль | | #5
Добавлено: 20.03.05 20:57
>Никакой разницы между VarPtr(tmp(0)) и addr нет.
Да я в курсе - просто забыл впереди приписать
addr=exGetAddrToRead - из проги выдирал...

>И вообще, что ты туда передаёшь?
Всмысле "что"? Массив с байтами, этот самый char, можно сказать. Когда пробовал строки передавать (на них я всё испытывал, чтобы убедиться, что всё передаётся нормально), то всё передавалось полностью, по крайней мере если я писал так:
EXPORT char* _stdcall exGetAddrToRead()
{
AddrToRead="Neco's char";
return AddrToRead;
}
то после всех этих манипуляций в библии-приёмнике я тоже получал "Neco's char", но тут возможно это из-за нуля на концевых строках так получалось, не знаю - по крайней мере со звуком глючит.
Кстати, счас пробовал сдигать таким вот макаром:
exAddThisToWrite VarPtr(tmp(0)) + 8, sz - 8
8 - то число при котором звук стал однородным, однако это только при sz=1000, а если установить sz=1600, то начинает так скрипеть, что слушать невозможно.

>Попробуй ReDim tmp(sz).
это так у меня собственно вначале так было, потом когда заметил глюк подумал внимательнее и пришёл к выводу, что раз я передаю sz байт, значит и массив у меня тоже должен быть sz байт, а учитывая нулевой выходит, что ReDim(sz-1) всё-таки правильнее.
Хотя не в этом суть - я могу его хоть sz*2 сделать - один фиг я использую только sz первых байт, а остальные будут только память забивать. А вот если я сделаю ReDim(sz-2), то получу вылетевший VB IDE, по причине Access Vilation, что свидетельствует о том, что размер буфера я всё-таки указал достаточный.
Я бы подумал, что я плохой сишник (что безусловно не так), если бы вся эта канитель не работала бы в случае
exAddThisToWrite exGetAddrToRead, sz
из чего следует, что код библиотек здесь ни при чём и то, что я плохой vb'шник. 8)

Ответить

Номер ответа: 6
Автор ответа:
 Neco



ICQ: 247906854 

Вопросов: 133
Ответов: 882
 Web-сайт: neco.pisem.net
 Профиль | | #6
Добавлено: 20.03.05 20:58
2Cresta: массив я буду обрабатывать позже - мне сейчас надо добиться, чтобы напрямую работало, а раз без CopyMemory и промежуточного массива всё тип-топ, то я думаю, что дело тут именно в промежуточных вычислениях...

Ответить

Номер ответа: 7
Автор ответа:
 cresta



Вопросов: 117
Ответов: 1538
 Профиль | | #7 Добавлено: 20.03.05 21:28
CopyMemory наверное объявлена (Dest As Any.... ?
Попробуй объяви (ByVal Dest As Long.... и затем CopyMemory ByVal VarPtr(Tmp(0)),......

Проверить ошибочность промежуточных вычислений можно IsBadReadPtr(byval VarPtr(Tmp(0)),sz)

Ответить

Номер ответа: 8
Автор ответа:
 cresta



Вопросов: 117
Ответов: 1538
 Профиль | | #8 Добавлено: 21.03.05 00:27
Хе, сейчас сделал такой эксперимент:
1.В dll сделал два одинаковых байтовых массива. По 100 байт. Проверил - совпадают.
2.Один оставил как тестовый(проверочный). Адрес второго передал в VB. И тут же из VB вернул обратно этот адрес в dll (в проверочную ф-цию). Безо всяких CopyMemory, напрямую. Проверил адрес - тот же, что и передавал в VB. Не изменился. А содержимое первых 100 байт от этого адреса запорото напрочь :( Есть только небольшая последовательность от 18 до 31 байта, совпадающая с исходным содержимым. Вот так вот.

Ответить

Номер ответа: 9
Автор ответа:
 CyRax



Разработчик Offline Client

ICQ: 204447456 

Вопросов: 180
Ответов: 4229
 Web-сайт: basicproduction.nm.ru
 Профиль | | #9
Добавлено: 21.03.05 00:43
Ну тогда можно попробовать передавать ByVal As String. С этим проблем вроде у VB нету.

Ответить

Номер ответа: 10
Автор ответа:
 Neco



ICQ: 247906854 

Вопросов: 133
Ответов: 882
 Web-сайт: neco.pisem.net
 Профиль | | #10
Добавлено: 21.03.05 01:08
2CyRax: мне потом этот массив сжимать ещё, а алгоритмы сжатия у меня тока под массивы - переписывать их под строки я не хочу, т.к. для этого в них надо въехать, а это долго...
2cresta: да не, в моих вроде ничего не терялось, тока вот есть ощущение, что т.к. си для показа строк ориентируется на нулевой символ, то и строки он мне показывал нормально, а вот счас написал фукцию, чтобы он всё, что передаёт звуковому драйверу, писал в файл и выяснилось, что при передаче адреса напрямую (без CopyMemory и массива) длина записываемого в файл больше моего буфера (sz) на 5 байт стабильно. Вот они:
ээээ‘
А при передаче массива на 4:
яяяя
что более логично, но всё равно непонятно...
но в общем проблему я обошёл, нехорошо, конечно, я сделал, но сделал:
EXPORT int _stdcall exAddThisToWrite(int addr,int arrSize)
{
char *refArr;
refArr = (char *)GlobalAlloc (GMEM_FIXED, arrSize);
strncpy(refArr,(char*)addr,arrSize);
//далее можно юзать refArr по-нормальному...
........................
........................
........................
}

Ответить

Номер ответа: 11
Автор ответа:
 CyRax



Разработчик Offline Client

ICQ: 204447456 

Вопросов: 180
Ответов: 4229
 Web-сайт: basicproduction.nm.ru
 Профиль | | #11
Добавлено: 21.03.05 02:20

мне потом этот массив сжимать ещё, а алгоритмы сжатия у меня тока под массивы

 Не вижу проблемы, используй StrConv.

Ответить

Номер ответа: 12
Автор ответа:
 CyRax



Разработчик Offline Client

ICQ: 204447456 

Вопросов: 180
Ответов: 4229
 Web-сайт: basicproduction.nm.ru
 Профиль | | #12
Добавлено: 21.03.05 02:40

длина записываемого в файл больше моего буфера (sz) на 5 байт стабильно

 Ну так и показал бы как этот sz получаешь, а то получается что ошибка была как раз в том куске, который ты не предоставил.

Ответить

Номер ответа: 13
Автор ответа:
 CyRax



Разработчик Offline Client

ICQ: 204447456 

Вопросов: 180
Ответов: 4229
 Web-сайт: basicproduction.nm.ru
 Профиль | | #13
Добавлено: 21.03.05 02:43

что т.к. си для показа строк ориентируется на нулевой символ,

 Ну так ReDim tmp(sz) и преобразовывал твой массив в строку типа ASCIIZ, которая ничем иным как байтовый массив с нулевым байтом в конце не является.

Ответить

Номер ответа: 14
Автор ответа:
 cresta



Вопросов: 117
Ответов: 1538
 Профиль | | #14 Добавлено: 21.03.05 13:09
Neco, я тут нашёл, почему массив искажался, может у тебя тоже в этом проблема (твоего кода не видно, поэтому точно не скажу):
Массив был локальным, т.е. на стеке. Передал адрес в VB, вышел из процедуры и память, где находился масив, стала доступна для программы и она затерла его. Убрал массив из стека в секцию данных - искажать перестало.
Попробуй сделать все свои массивы глобальными, как те что передаёшь в VB, так и те, которые являются временными (tmp). Думаю проблема исчезнет.
У тебя процедура воспроизведения звука из массива если асинхронная, то запустив музыку и покинув пределы процедуры, ты освобождаешь всю локальную память (в т.ч. и место под массив) и программа может записать туда все что угодно.

Ответить

Номер ответа: 15
Автор ответа:
 cresta



Вопросов: 117
Ответов: 1538
 Профиль | | #15 Добавлено: 21.03.05 13:36
И ещё вот об это споткнулся:
char* _stdcall exGetAddrToRead()
сделай его
unsigned char* _stdcall exGetAddrToRead()
VB работает с байтом 0-255, а char - -128-127

Это тоже может быть причина искажений.

Ответить

Страница: 1 | 2 | 3 |

Поиск по форуму



© Copyright 2002-2011 VBNet.RU | Пишите нам