-
NoXXX (18.07.07 13:34) [0]Всем доброго здоровья.
Проблема заключается вот в чем. У меня есть считыватель карт, вместе с которым идет ActiveX-компонент для работы с ним. Импортировал я библиотеку типов, там присутствует следующее:
type
PrivateAlias1 = array[0..7] of Byte;
В описании функций этот тип передается в качестве параметра:
function WriteSecurityKey_FN(nKey: Smallint; baKey: PrivateAlias1): Integer; dispid 46;
При компиляции модуля на каждую такую функцию выдаётся ошибка:
[Error] ESDKLib_TLB.pas [XXX]: Illegal type in OLE automation section: 'PrivateAlias1'
Порывшись в инете я понял, что массив байт - это COM-несовместивый тип данных, и что нужно пользоваться функцией VarArrayCreate, предварительно описав этот PrivateAlias1 как OleVariant.
Вот кусок кода:
procedure TForm1.Button1Click(Sender: TObject);
var
card : IACOS1Card;
fil : ISCardFile;
myICCODE : OleVariant;
begin
MyICCode := VarArrayCreate([0,7], varByte);
myICCODE[0] := $41; // A
myICCODE[1] := $43; // C
myICCODE[2] := $4F; // O
myICCODE[3] := $53; // S
myICCODE[4] := $54; // T
myICCODE[5] := $45; // E
myICCODE[6] := $53; // S
myICCODE[7] := $54; // T
card := CoACOS1Card.Create;
card.LoadReaderList();
card.Connect(card.GetReaderName(0));
card.SubmitCode_FN(IC_CODE, myICCODE);
fil := CoSCardFile.Create;
card.CreateFile(fil);
card.Disconnect;
card.ReleaseContent;
end;
При выполнении функции SubmitCode_FN вываливается exception (EAccessViolation) в модуле ESDK.dll, т.е., насколько я понимаю, эта самая библиотека не воспринимает myICCODE как массив.
Помогите, пожалуйста, я уже не знаю что делать.
PS: ESDK.dll изначально написана на Си.
PPS: В исходниках ESDK.dll функция описана как STDMETHODIMP CACOS1Card::SubmitCode_FN(SHORT nKey,BYTE baKey[8],BOOL* bSuccess)
В Си я "не в зуб ногой", так что не знаю, поможет ли это уточнение или нет :/ -
попробуй int64
function WriteSecurityKey_FN(nKey: Smallint; baKey: int64): Integer; dispid 46;
type
TInt64Rec=packed record
case boolean of
false: (AsArray: array[0..7] of Byte);
true: (AsInt64:int64);
end;
myICCODE : TInt64Rec;
begin
myICCODE.AsArray[0] := $41; // A
myICCODE.AsArray[1] := $43; // C
myICCODE.AsArray[2] := $4F; // O
myICCODE.AsArray[3] := $53; // S
myICCODE.AsArray[4] := $54; // T
myICCODE.AsArray[5] := $45; // E
myICCODE.AsArray[6] := $53; // S
myICCODE.AsArray[7] := $54; // T
card.SubmitCode_FN(IC_CODE, myICCODE.AsInt64); -
Сергей М. © (18.07.07 14:08) [2]
> вместе с которым идет ActiveX-компонент для работы с ним
И примеров его использования в комплекте поставки нет ? -
NoXXX (18.07.07 14:15) [3]SlymRO
Попробовал, вылетает такое же исключение :( Читаю, пишут что массивы должны передаваться как SafeArray, но не пойму, как это сделать можно :/ -
NoXXX (18.07.07 14:15) [4]Сергей М
Пример есть, но он на C#, и там всё работает без проблем. А нужно на Delphi написать. -
Сергей М. © (18.07.07 14:19) [5]
> Пример есть, но он на C#
ПРиводи его сюда .. -
NoXXX (18.07.07 14:24) [6]Вот на C#:
card.LoadReaderList()
string strReader = card.GetReaderName( 0 );
card.Connect( strReader );
byte[] baIC_CODE = Str2ByteAr("ACOSTEST");
card.SubmitCode_FN( (int)SUB_CODE.IC_CODE, baIC_CODE);
Как я понимаю, byte[] - это как раз и есть массив байт -
Сергей М. © (18.07.07 14:27) [7]
> В описании функций этот тип передается в качестве параметра:
>
>
> function WriteSecurityKey
А где собссно TLB-описание метода SubmitCode_FN ?
ПРиведи .. -
NoXXX (18.07.07 14:29) [8]
> А где собссно TLB-описание метода SubmitCode_FN ?
Ай, ошибся, извините :)
function SubmitCode_FN(nSubmitKey: Smallint; baKey: PrivateAlias1): Integer; dispid 47;
В принципе, то же самое. -
> SubmitCode_FN(SHORT nKey,BYTE baKey[8],BOOL* bSuccess)
судя по всему, метод ждет от Вас адреса первого элемента массива. Передавая же SafeArray вы передаете адрес служебной структуры. Передавая емуmyICCODE.AsInt64
вы передаете 8-байтовое число, которое интерпретируется как адрес. Поэтому попробуйте в [1] заменить
card.SubmitCode_FN(IC_CODE, myICCODE.AsInt64);
на
card.SubmitCode_FN(IC_CODE, @myICCODE); -
> function SubmitCode_FN(nSubmitKey: Smallint; baKey: PrivateAlias1):
> Integer; dispid 47;
и декларацию тоже надо поправить, конечно -
NoXXX (18.07.07 14:37) [11]
> Поэтому попробуйте в [1] заменить card.SubmitCode_FN(IC_CODE,
> myICCODE.AsInt64);на card.SubmitCode_FN(IC_CODE, @myICCODE);
>
наcard.SubmitCode_FN(IC_CODE, @myICCODE)
ругается на несовместимость типов Int64 и Pointer :( -
NoXXX (18.07.07 14:39) [12]
> и декларацию тоже надо поправить, конечно
Пробовал декларацию править, PrivateAlias на pointer - ругается, Illegal type in OLE automation section 'pointer'. Не хочет принимать указатель он :( -
NoXXX (18.07.07 14:47) [13]Попробовал в [1] вместо Int64 использовать String. Значение принял, не ругнулся, но выскочила ошибка, говорящая, что код неверен. Т.е. метод значение получил, но не 'ACOSTEST'. Куда еще можно копать?
-
да, надо все по науке :)type
type
TPrivateArray = array[0..7] of Byte;
PPrivateArray = ^TPrivateArray;
{................................}
var
myICCODE : TPrivateArray;
mypointer: PPrivateArray;
{....................................}
begin
myICCODE[0] := $41; // A
myICCODE[1] := $43; // C
myICCODE[2] := $4F; // O
myICCODE[3] := $53; // S
myICCODE[4] := $54; // T
myICCODE[5] := $45; // E
myICCODE[6] := $53; // S
myICCODE[7] := $54; // T
mypointer := @myICCODE;
card.SubmitCode_FN(IC_CODE, Integer(mypointer)); -
соответственноtype
PrivateAlias1 = Integer; -
NoXXX (18.07.07 15:24) [16]Спасибо! Получилось! :)
-
тогда и это должно сработать:Integer(pointer(PChar('ACOSTEST')))