Страница 1 из 2
Размерность массива
Добавлено: 14 Июль 2014, 22:41
dsabitov
Доброго дня, единомышленники!
Можно ли как-то переопределить размерность массива структуры GROUP?
Приведенный ниже код работает отлично:
Код: Выделить всё
PROGRAM
OMIT('***')
* Created with Clarion 8.0
* User: dsabitov
* Date: 14.07.2014
* Time: 21:57
***
MAP
ICanRedim PROCEDURE(LONG DIM_size)
END
CODE
ICanRedim(10)
ICanRedim PROCEDURE(LONG DIM_size)
LongVar LONG,DIM(DIM_size)
CODE
sz# = MAXIMUM(LongVar, 1)
MESSAGE('My dimension size is ' & sz#)
А вот такой код не может даже откомпилироваться:
Код: Выделить всё
PROGRAM
OMIT('***')
* Created with Clarion 8.0
* User: dsabitov
* Date: 14.07.2014
* Time: 21:57
***
MAP
ICanRedim PROCEDURE(LONG DIM_size)
END
CODE
ICanRedim(10)
ICanRedim PROCEDURE(LONG DIM_size)
MyStruct GROUP,DIM(DIM_size)
Man STRING(20)
Phone STRING(20)
END
CODE
sz# = MAXIMUM(MyStruct, 1)
MESSAGE('My dimension size is ' & sz#)
Ошибка: 'Variable size must be constant'.
Вопрос не праздный - нужно определять количество структур MyStruct для того, чтобы прочитать их в коде программы. Сама структура заполняется процедурой из внешней (не Clarion) dll. Эта внешняя процедура определяет и количество таких структур.
Вот так выглядит определение процедуры:
MODULE('wbotho.lib')
check_file_sign(*CSTRING fileName,*BYTE arraySize,*LONG arrayPointer),SHORT,RAW,C,PROC ! здесь arrayPointer - указатель на массив структур размерности arraySize
END
Может кто-то сталкивался с такой проблемой? Как решили?
Re: Размерность массива
Добавлено: 15 Июль 2014, 13:18
IKSoft
Как-то так
Код: Выделить всё
loc:Counts long
loc:aPtr long
tgCheck_Status group,type
szName cstring(NAME_LEN )
szAlias cstring(ALIAS_LEN )
bPosition byte
bStatus byte
lDate long
.
tagCheck_Status group,type
a group(tgCheck_Status),dim(1)
.
.
pagCheck_Status &tagCheck_Status
code
.....
if loc:lKeyCount
loc:counts = 0
loc:ret = self.pcWBotho.mCheck_File_Sign_Ex(address(loc:szFileOut), address(loc:aLong), loc:lKeyCount, address(loc:counts), address(loc:aPtr))
if loc:ret
self.pcWBotho.mShowError(loc:ret, 'mCheck_File_Sign_Ex', loc:szFileOut)
else
if loc:aPtr
pagCheck_Status &= (loc:aPtr)
loop loc:j = 1 to loc:counts
qTrace.Str = choose(pagCheck_Status.a[loc:j].bStatus+1, ' OK' ,' Bad' ,'Not found')&|
' KeyName: ' & clip(pagCheck_Status.a[loc:j].szName) &|
'. Alias: '&clip(pagCheck_Status.a[loc:j].szAlias)&|
', N '&pagCheck_Status.a[loc:j].bPosition&|
', Status: '&pagCheck_Status.a[loc:j].bStatus
do add_Trace
.
self.pcWBotho.mFreeMemory(loc:aPtr)
loc:aPtr = 0
!Remove Signs
if g24.fRemoveSign = '1'
loc:ret = self.pcWBotho.mDelSign(address(loc:szFileOut), -1)
if loc:ret
else
.
.
.
.
.
Re: Размерность массива
Добавлено: 15 Июль 2014, 14:08
dsabitov
Спасибо за ответ - вижу Вы в теме.
Получается, у Вас срабатывает pagCheck_Status.a[loc:j].szName.
То что pagCheck_Status.a[1].szName не вызовет ошибки понятно, так как группа pagCheck_Status.a объявлена как массив размерности 1 с одним элементом, а вот что будет если loc:j станет равным 2?
Обращение pagCheck_Status.a[2].szName разве не создает ошибку типа subscript out of range? Как Вы снимаете с файла скажем 2 (а не одну) подписи? Если все работает - какая у Вас версия Clarion? Если я чего-то не понимаю - прошу объяснить....
Re: Размерность массива
Добавлено: 15 Июль 2014, 14:46
IKSoft
Все работает
Clarion 6.3
Отключена галочка Project - GlobalOptions - RunTime Checks - ArrayIndex
Re: Размерность массива
Добавлено: 15 Июль 2014, 17:14
dsabitov
Видимо в 8-й версии такой вариант не проходит. По крайней мере у меня не получилось...
Re: Размерность массива
Добавлено: 15 Июль 2014, 17:45
IKSoft
Покажите Ваш код
Что не так?
попробуйте объявить
check_file_sign(long szFN, long arraySize,long arrayPointer),SHORT,RAW,C,PROC
и вызывать
Check_File_Sign(address(loc:szFileOut), address(loc:counts), address(loc:aPtr))
Re: Размерность массива
Добавлено: 17 Июль 2014, 11:09
dsabitov
Добрый день. В том-то и дело, что все работает. Ниже код программы, который у меня работает:
Код: Выделить всё
PROGRAM
OMIT('***')
* Created with Clarion 8.0
* User: dsabitov
* Date: 09.07.2014
* Time: 9:52
*
* To change this template use Tools | Options | Coding | Edit Standard Headers.
***
MAP
MODULE('WBOTHO.LIB')
CryptoInit(*CSTRING, *CSTRING),SHORT,RAW,C,PROC
CryptoDone(),SHORT,RAW,C,PROC
SignInit(*CSTRING, *CSTRING),SHORT,RAW,C,PROC
SignDone(),SHORT,RAW,C,PROC
check_file_sign(*CSTRING,*BYTE ,*LONG),SHORT,RAW,C,PROC
FreeMemory(LONG),RAW,C,PROC
END
CFS PROCEDURE(BYTE array_size, LONG array_address)
END
INCLUDE('e-codes.clw')
INCLUDE('equates.clw')
Check_Status_Ptr LONG
GV:pathToBase CSTRING(256)
GV:pathToSecret CSTRING(256)
GV:TestSignedFile CSTRING(FILE:MaxFilePath+FILE:MaxFileName)
NAME_LEN EQUATE(12)
ALIAS_NAME EQUATE(120)
Count BYTE
stat_array GROUP,TYPE
Name CSTRING(NAME_LEN+1)
Alias CSTRING(ALIAS_NAME+1)
Position BYTE
Status BYTE
Date ULONG
END
CODE
GV:pathToBase = CLIP(GETINI('key-store','pathToBase', ,'.\swENC.ini'))
GV:pathToSecret= CLIP(GETINI('key-store','pathToSecret',,'.\swENC.ini'))
GV:TestSignedFile='C:\Temp\a.txt'
SignInit(GV:pathToSecret,GV:pathToBase)
check_file_sign(GV:TestSignedFile,count,Check_Status_Ptr)
CFS(Count,Check_Status_Ptr)
SignDone()
FreeMemory(Check_Status_Ptr)
SignInit(GV:pathToSecret,GV:pathToBase)
check_file_sign(GV:TestSignedFile,count,Check_Status_Ptr)
CFS(Count,Check_Status_Ptr)
SignDone()
FreeMemory(Check_Status_Ptr)
MESSAGE('Program Complete!')
CFS PROCEDURE(BYTE array_size, LONG array_address)
sa GROUP(stat_array),DIM(16)
END
CODE
PEEK(array_address,sa)
MESSAGE('Count = ' & array_size & '. Array address = ' & array_address)
MESSAGE('Alias 1 = ' & CLIP(sa[1].Alias) & '. Date = ' & sa[1].Date & '. Name = ' & CLIP(sa[1].Name) & '. Position = ' & sa[1].Position & '. Status = ' & sa[1].Status)
MESSAGE('Alias 2 = ' & CLIP(sa[2].Alias) & '. Date = ' & sa[2].Date & '. Name = ' & CLIP(sa[2].Name) & '. Position = ' & sa[2].Position & '. Status = ' & sa[2].Status)
Но!!! Мне приходится объявлять в процедуре CFS массив sa, имеющий заведомо большее количество элементов (16), чем может иметься подписей на файле. И все из-за того, что я не могу вместо объявления
написать
Re: Размерность массива
Добавлено: 17 Июль 2014, 18:46
PavelNK
А чем не устраивает QUEUE?
Re: Размерность массива
Добавлено: 17 Июль 2014, 23:10
dsabitov
Я пробовал использовать QUEUE вместо Group (с той же структурой, пробовал 2 варианта - засылал адрес пустой QUEUE и адрес QUEUE, в которую предвратиельно добавлял array_size строк) - процедура ее не заполняет.
Re: Размерность массива
Добавлено: 18 Июль 2014, 10:17
kreator
dsabitov писал(а):Я пробовал использовать QUEUE вместо Group (с той же структурой, пробовал 2 варианта - засылал адрес пустой QUEUE и адрес QUEUE, в которую предвратиельно добавлял array_size строк) - процедура ее не заполняет.
Этого не может быть. У меня очень много кода, который использует передачу Queue через заголовок процедуры и заполнения её в процедуре.
Re: Размерность массива
Добавлено: 18 Июль 2014, 11:41
dsabitov
Так и есть, просто в данном случае структуру QUEUE должна заполнить НЕ кларионовская процедура, которая про QUEUE мало что знает. Эта процедура ТОЧНО заполняет структуру GROUP с правильно заданной размерностью массива. Возможно какие-то другие внешние (не кларионовские) функции корректно заполняют QUEUE - но в моем случае этого не происходит. Возможно, я не правильно объявляю структуру QUEUE... Я пробовал такие варианты:
Код: Выделить всё
sa QUEUE(stat_array)
END
! и так пробовал
qsa QUEUE
sa GROUP(stat_array),DIM(1)
END
END
Re: Размерность массива
Добавлено: 18 Июль 2014, 14:08
kreator
Попробуй подсунуть внешней процедуре очередь, RECORD которой повторяет группу:
stat_array Queue
Name CSTRING(NAME_LEN+1)
Alias CSTRING(ALIAS_NAME+1)
Position BYTE
Status BYTE
Date ULONG
END
Типа такого.
Если не прокатит, то. Судя по хелпу восьмёрочному, должно быть всё ровно, нет никаких ограничений на массив группы. Поэтому, есть вероятность, что это очередной баг 8-ки. Нужно эксперимент провести на другой версии. Я сталкиваюсь с массой мелких недоработок и странностей в 8-ке, и уже не хочется рыть землю, просто надо перейти на 9-ку и всё.
Re: Размерность массива
Добавлено: 18 Июль 2014, 14:41
dsabitov
Вот такая незатейливая программа
Код: Выделить всё
PROGRAM
OMIT('***')
* Created with Clarion 9.0
* User: dsabitov
* Date: 18.07.2014
* Time: 14:31
*
* To change this template use Tools | Options | Coding | Edit Standard Headers.
***
MAP
Resize PROCEDURE(BYTE NewSize)
END
CODE
Resize(15)
MESSAGE('Complete')
RETURN
Resize PROCEDURE(BYTE NewSize)
G GROUP,DIM(NewSize)
Name STRING(20)
Phone STRING(20)
END
CODE
RETURN
компилируется с ошибкой "Variable-size must be constant" и в 8 и в 9. Если у кого не так - напишите.
Re: Размерность массива
Добавлено: 18 Июль 2014, 15:53
IKSoft
Внешняя процедура должна получить адрес переменной, куда она, в эту переменную, запишет адрес массива,
так делают многие функции winAPI
У меня всегда работала моя "схема".
Вы мне так и не ответили, что не так у вас, если использовать мою схему?
Re: Размерность массива
Добавлено: 20 Июль 2014, 19:46
dsabitov
Ответ содержится в переписке выше. Насчет поыток засылать не АДРЕС GROUP а адрес QUEUE - результат отрицательный. Завтра выложу точное описание функции, которая заполняет массив - копию из документации.
Вот описание из документации:
Код: Выделить всё
Для проверки подписи под файлом служит функция check_file_sign(wbotho, wsigno), которая имеет следующий прототип:
T16bit WINAPI check_file_sign (char *file_name,
P8bit count,
Check_Status_Ptr *stat_array);
Функция имеет следующие параметры:
(i) file_name — указатель на строку полного пути к файлу;
(o) count — указатель на переменную, в которую записывается количество обнаруженных подписей;
(o) stat_array — массив результатов проверки каждой подписи, элементами которого являются структуры (структура описана в файле verba.h):
#define NAME_LEN 12
#define NAME_LEN 120
typedef struct tagCheck_Status {
char Name[NAME_LEN+1];
char Alias[ALIAS_LEN+1];
T8bit Position;
T8bit Status;
T32bit Date;
} Check_Status;
typedef Check_Status *Check_Status_Ptr;
#define CHECK_STATUS_LEN sizeof(Check_Status)
• Каждая структура содержит:
• идентификатор ключа;
• описание (текстовые атрибуты);
• порядковый номер подписи;
• гринвическое время (UTC) формирования подписи (time_t);
Внимание. Данный формат для времени формирования подписи используется начиная с версии библиотек СКЗИ 5.0 .
• результат проверки:
0 = CORRECT — подпись верна;
1 = NOT_CORRECT — подпись не верна;
2 = OKEY_NOT_FOUND — открытый ключ для проверки подписи не найден.
Внимание. Память под этот массив отводится внутри функции check_file_sign и должна быть освобождена функцией FreeMemory (см. п. 8.12), как только stat_array будет обработан.
Пример использования функции check_file_sign:
unsigned char count;
Check_Status_Ptr status_array;
...
error_code = check_file_sign("C:\\TEST.TST", &count, &status_array);
if(error_code) return(error_code);
for(i = 0; i < count; i++)
printf("%u-%u\n", status_array[i].Position, status_array[i].Status);
FreeMemory(status_array);