Размерность массива

Clarion, Clarion 7

Модератор: Дед Пахом

Правила форума
При написании вопроса или обсуждении проблемы, не забывайте указывать версию Clarion который Вы используете.
А так же пользуйтесь спец. тегами при вставке исходников!!!
dsabitov
Посетитель
Сообщения: 44
Зарегистрирован: 02 Апрель 2011, 12:30

Размерность массива

Сообщение 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

Может кто-то сталкивался с такой проблемой? Как решили?
IKSoft
Посетитель
Сообщения: 42
Зарегистрирован: 27 Май 2010, 13:38

Re: Размерность массива

Сообщение 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
                    .
                 .
              .
          .
      .
dsabitov
Посетитель
Сообщения: 44
Зарегистрирован: 02 Апрель 2011, 12:30

Re: Размерность массива

Сообщение 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? Если я чего-то не понимаю - прошу объяснить....
IKSoft
Посетитель
Сообщения: 42
Зарегистрирован: 27 Май 2010, 13:38

Re: Размерность массива

Сообщение IKSoft »

Все работает
Clarion 6.3

Отключена галочка Project - GlobalOptions - RunTime Checks - ArrayIndex
dsabitov
Посетитель
Сообщения: 44
Зарегистрирован: 02 Апрель 2011, 12:30

Re: Размерность массива

Сообщение dsabitov »

Видимо в 8-й версии такой вариант не проходит. По крайней мере у меня не получилось...
IKSoft
Посетитель
Сообщения: 42
Зарегистрирован: 27 Май 2010, 13:38

Re: Размерность массива

Сообщение 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))
dsabitov
Посетитель
Сообщения: 44
Зарегистрирован: 02 Апрель 2011, 12:30

Re: Размерность массива

Сообщение 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), чем может иметься подписей на файле. И все из-за того, что я не могу вместо объявления

Код: Выделить всё

sa                      GROUP(stat_array),DIM(16)
                        END
написать

Код: Выделить всё

sa                      GROUP(stat_array),DIM(array_size)
                        END
PavelNK
Старожил
Сообщения: 262
Зарегистрирован: 15 Март 2011, 8:02

Re: Размерность массива

Сообщение PavelNK »

А чем не устраивает QUEUE?
dsabitov
Посетитель
Сообщения: 44
Зарегистрирован: 02 Апрель 2011, 12:30

Re: Размерность массива

Сообщение dsabitov »

Я пробовал использовать QUEUE вместо Group (с той же структурой, пробовал 2 варианта - засылал адрес пустой QUEUE и адрес QUEUE, в которую предвратиельно добавлял array_size строк) - процедура ее не заполняет.
kreator
✯ Ветеран ✯
Сообщения: 5007
Зарегистрирован: 28 Май 2009, 15:54
Откуда: Москва
Благодарил (а): 7 раз
Поблагодарили: 21 раз

Re: Размерность массива

Сообщение kreator »

dsabitov писал(а):Я пробовал использовать QUEUE вместо Group (с той же структурой, пробовал 2 варианта - засылал адрес пустой QUEUE и адрес QUEUE, в которую предвратиельно добавлял array_size строк) - процедура ее не заполняет.
Этого не может быть. У меня очень много кода, который использует передачу Queue через заголовок процедуры и заполнения её в процедуре.
We are hard at work… for you. :)
dsabitov
Посетитель
Сообщения: 44
Зарегистрирован: 02 Апрель 2011, 12:30

Re: Размерность массива

Сообщение dsabitov »

Так и есть, просто в данном случае структуру QUEUE должна заполнить НЕ кларионовская процедура, которая про QUEUE мало что знает. Эта процедура ТОЧНО заполняет структуру GROUP с правильно заданной размерностью массива. Возможно какие-то другие внешние (не кларионовские) функции корректно заполняют QUEUE - но в моем случае этого не происходит. Возможно, я не правильно объявляю структуру QUEUE... Я пробовал такие варианты:

Код: Выделить всё

sa                      QUEUE(stat_array)
                        END
! и так пробовал
qsa                      QUEUE
sa                        GROUP(stat_array),DIM(1)
                          END
                        END
kreator
✯ Ветеран ✯
Сообщения: 5007
Зарегистрирован: 28 Май 2009, 15:54
Откуда: Москва
Благодарил (а): 7 раз
Поблагодарили: 21 раз

Re: Размерность массива

Сообщение 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-ку и всё.
We are hard at work… for you. :)
dsabitov
Посетитель
Сообщения: 44
Зарегистрирован: 02 Апрель 2011, 12:30

Re: Размерность массива

Сообщение 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. Если у кого не так - напишите.
IKSoft
Посетитель
Сообщения: 42
Зарегистрирован: 27 Май 2010, 13:38

Re: Размерность массива

Сообщение IKSoft »

Внешняя процедура должна получить адрес переменной, куда она, в эту переменную, запишет адрес массива,
так делают многие функции winAPI
У меня всегда работала моя "схема".

Вы мне так и не ответили, что не так у вас, если использовать мою схему?
dsabitov
Посетитель
Сообщения: 44
Зарегистрирован: 02 Апрель 2011, 12:30

Re: Размерность массива

Сообщение 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);
Последний раз редактировалось dsabitov 21 Июль 2014, 9:11, всего редактировалось 1 раз.
Ответить