Типы данных

Clarion, Clarion 7

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

Правила форума
При написании вопроса или обсуждении проблемы, не забывайте указывать версию Clarion который Вы используете.
А так же пользуйтесь спец. тегами при вставке исходников!!!
Ответить
mike_ch
Бывалый
Сообщения: 62
Зарегистрирован: 11 Июль 2007, 14:21
Откуда: Беларусь, Минск

Типы данных

Сообщение mike_ch »

Помогите пожалуйста с типами данных. Необходимо описать функцию API. В заголовке файла C есть следующие структуры

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

/***** CMBOXINFO *****/
typedef struct __CMBOXINFO {
  CMBYTE mbMajorVersion;
  CMBYTE mbMinorVersion;
  CMUSHORT musBoxMask;
  CMULONG mulSerialNumber;
  CMUSHORT musBoxKeyId;
  CMUSHORT musUserKeyId;
  CMBYTE mabBoxPublicKey[CM_PUBLIC_KEY_LEN];
  CMBYTE mabSerialPublicKey[CM_PUBLIC_KEY_LEN];
  CMULONG mulReserve;
} CMBOXINFO;

typedef struct __TCMACCESS {
  CMULONG mflCtrl;
  CMULONG mulFirmCode;
  CMULONG mulProductCode;
  CMULONG mulFeatureCode;
  CMULONG mulUsedRuntimeVersion;
  CMULONG midProcess;
  CMUSHORT musProductItemReference;
  CMUSHORT musSession;
  unsigned char    mabIPv4Address[4];
  CMBOXINFO mcmBoxInfo;
} TCMACCESS;

Правильно ли я их объявляю в Clarion'е

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

CMBOXINFO           group, type
mbMajorVersion          byte
mbMinorVersion          byte
musBoxMask              ushort
mulSerialNumber         ulong
musBoxKeyId             ushort
musUserKeyId            ushort
mabBoxPublicKey         byte, dim(64)
mabSerialPublicKey      byte, dim(64)
mulReserve              ulong
                    end

TCMACCESS            group, type
mflCtrl                 ulong
ulFirmCode              ulong
mulProductCode          ulong
mulFeatureCode          ulong
mulUsedRuntimeVersion   ulong
midProcess              ulong
musProductItemReference ushort
musSession              ushort
mabIPv4Address          pstring(4)
mcmBoxInfo              group(CMBOXINFO).
                        end
Дело в том, что используемая API функция отрабатывается без ошибок (возвращает нужный мне handle). Но она должна заполнить переменную структуры TCMACCESS. И после отработки функции рушится приложение

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

Exception occurred at address 01116814
Exception code C0000005: Access Violation
Process PID=5020  Image: D:\work\clarion8\cmapi\cmapi.Exe
Thread 1  Handle=000000C4  TID=3668

EAX=00000000    EBX=00401519    ECX=00000001    EDX=00000000
ESI=00000000    EDI=002B8E5D    EBP=00000000    ESP=0012FCD8
EIP=01116814    FLG=00010246

Call Stack:
01116814
Т.е. я думаю, что проблема именно в том, что я неправильно объявил структуру данных.
Аватара пользователя
Дед Пахом
Старичок
Сообщения: 3133
Зарегистрирован: 07 Июль 2005, 16:51
Откуда: Москва, Россия
Благодарил (а): 10 раз
Поблагодарили: 28 раз
Контактная информация:

Re: Типы данных

Сообщение Дед Пахом »

mabIPv4Address pstring(4)
Меня pstring смущает, почему не просто string(4)? И проверьте декларацию функции, RAW, PASCAL или RAW,C наверняка должны быть.
С уважением, ДП
mike_ch
Бывалый
Сообщения: 62
Зарегистрирован: 11 Июль 2007, 14:21
Откуда: Беларусь, Минск

Re: Типы данных

Сообщение mike_ch »

Спасибо.
Действительно в декларации функции косяк был. Надо RAW,C.
Прокатывает и pstring(4) и string(4).
mike_ch
Бывалый
Сообщения: 62
Зарегистрирован: 11 Июль 2007, 14:21
Откуда: Беларусь, Минск

Re: Типы данных

Сообщение mike_ch »

Опять объявилась та же ошибка. Но теперь уже в api функции использует следующий тип данных

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

typedef DWORD RB_SPRO_APIPACKET[257]
Число 257 сам заранее высчитал, иначе там через 8 структур объявлять надо :).
Я этот тип данных описал след. образом

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

RB_SPRO_APIPACKET  group, type
var                     ulong, dim(257)
                    end
Сомневаюсь, что верно. Если не верно, то как описать тип данных, указывающий на массив DWORD?
Аватара пользователя
StillZero
Ветеран
Сообщения: 454
Зарегистрирован: 06 Июль 2005, 2:17
Откуда: Хабаровск
Контактная информация:

Re: Типы данных

Сообщение StillZero »

Не важно вообще как описывать, главное совпадение по числу байт и дальнейшее удобство разбора. Т.е. DWORD можно описать и как STRING(4), а BYTE как STRING(1).
У меня сомнения, конечно, по поводу необходимости наличия такого массива... странно как то... в общем можно сделать так:
var_buffer STRING(1028), где 1028 = 4*257
хотя и как ты сделал тоже покатит :)

а насчет RAW,C скорее всего неверно... ибо все Windows API должны передавать в PASCAL

The C and PASCAL attributes of a PROCEDURE prototype specifies that parameters are always passed on the stack. In 32-bit programs, both C and PASCAL conventions pass the parameters to the stack from right to left. The difference is in who (callee(C) or caller(PASCAL)) is cleaning the stack on return. Also, in C/C++ there is a difference in mangling of the external name, but in Clarion, name mangling is the same for both C and PASCAL. PASCAL is also completely compatible with the Windows API calling convention for 32-bit compiled applications--it is the Windows-standard calling convention (and also disables name mangling).

These calling conventions provide compatibility with third-party libraries written in other languages (if they were not compiled with a TopSpeed compiler). If you do not specify a calling convention in the prototype, the default calling convention is the internal, register-based parameter passing convention used by all the TopSpeed compilers.

Example:

MAP

MODULE('Party3.Obj') !A third-party library
Func46 PROCEDURE(*CSTRING,*REAL),REAL,C,RAW !Pass REAL then CSTRING, address-only
Func49 PROCEDURE(*CSTRING,*REAL),REAL,PASCAL,RAW !Pass CSTRING then REAL, address-only
END
END
Все сайты закрыты...
mike_ch
Бывалый
Сообщения: 62
Зарегистрирован: 11 Июль 2007, 14:21
Откуда: Беларусь, Минск

Re: Типы данных

Сообщение mike_ch »

StillZero писал(а): Не важно вообще как описывать, главное совпадение по числу байт и дальнейшее удобство разбора. Т.е. DWORD можно описать и как STRING(4), а BYTE как STRING(1).
Здесь вы абсолютно правы. У меня прокатила и моя декларация.
а насчет RAW,C скорее всего неверно... ибо все Windows API должны передавать в PASCAL
А вот здесь у меня вышло следующим образом. Немного предыстории...
У нашей небольшой компании есть программный продукт. Когда-то мы его защищали электронным ключом SafeNet Rainbow Technologies. Потом эти ключи нам перестали поставлять и теперь мы защищаемся немецким CodeMeter. Через некоторое время появилась необходимость определять серийный номер и тех и других. Эту возможность мне и необходимо было реализовать. Так вот, что у меня получилось.
API функции для CodeMeter работают с описанием RAW,C и никак иначе, а для SafeNet с описанием RAW,PASCAL.

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

module('win32')
    ! CodeMeter
    CmAccess(ulong, *TCMACCESS), long, raw, c
    CmGetInfo(long, ulong, *CMBOXINFO, ulong), long, raw, c

    ! SafeNet
    RNBOsproFormatPacket(*RB_SPRO_APIPACKET, ulong), ushort, raw, pascal
    RNBOsproInitialize(*RB_SPRO_APIPACKET), ushort, raw, pascal
    RNBOsproFindFirstUnit(*RB_SPRO_APIPACKET, ulong), ushort, raw, pascal
    RNBOsproRead(*RB_SPRO_APIPACKET, ulong, *ulong), ushort, raw, pascal
end
Ответить