Форум: "Основная";
Текущий архив: 2005.03.27;
Скачать: [xml.tar.bz2];
ВнизAccessViolation непонятно с чего Найти похожие ветки
← →
Alexandr3 (2005-03-10 08:49) [0]Ниже привожу код в котором при закоментировании строки
Element[5]:= "First_Name"; все проходит при раскоментированной строке отладчик выдает сабж уже на строке
@htinit := GetProcAddress(LibHandle,"HTINIT");
Помогите пожалуйста
Воообще если кто работал с HyTech Базами буду благодарен за небольшой пример создания таблицы.
var
Element:TElement;
httablecreate:Function(ptablename:Pchar;fpelement:TElement ;nElems:integer;fpCryptoKey:Pchar;fpReadPswd:Pchar;fpWritePswd:Pchar;nOpenMode:integer;fpHandle:THandle):integer;
htshut:function():integer;
gh:integer;
Form1: TForm1;
LibHandle:Thandle;
htinit:function(LangRus: pointer;rrr:Integer): integer;
implementation
uses htdefs;
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
begin
LibHandle:=LoadLibrary("HTW32PAS.DLL") ;
@htinit := GetProcAddress(LibHandle,"HTINIT");
@htTableCreate := GetProcAddress(LibHandle,"HTTABLECREATE");
htinit(nil,20) ;
Element[0]:=10;
Element[1]:=0;
Element[2]:= EC_FIELD;
Element[3]:=ET_CHAR;
Element[4]:=EK_NOTKEY;
Element[5]:= "First_Name";
//htTablecreate("c:\rtr",Element,1,"paswd",nil,nil,128,gh) ;
Edit1.Text:="dfva";
← →
Anatoly Podgoretsky © (2005-03-10 09:10) [1]А где объявление httablecreate в библиотеке, хочешь, чтобы мы помедитировали?
← →
Alexandr3 (2005-03-10 09:31) [2]Честно говоря не совсем понял вопрос учитывая что в данном случае
httablecreate не вызывается (закоментированна )
а при закоментированной
Element[5]:= "First_Name
адрес функции httablecreate возвращается нормально
Ниже описание функции из документации и еще
TElement oбъявлен как
type TElement=array[0..5] of variant;
htTableCreate - Создать новую таблицу
Назначение:
Функция служит для создания новой таблицы. Если таблица с заданным именем уже существует, поведение функции зависит от флага TAB_CREATE . Для сброшенного флага операция завершится с ошибкой. Если флаг установлен, функция уничтожит старую таблицу и создаст новую.
При создании или открытии СУБД присваивает таблице некий номер - "обработчик". Этот номер будет идентифицировать таблицу при последующих операциях поиска или обработки данных. При создании или открытии таблицы нужно указать флаги доступа, задающие режим использования таблицы (монопольный или совместный), возможность модификации данных и пр.
При задании ключа крипто-закрытия выполняется шифрование данных как в постоянной части таблицы, так и журнале изменений. Также шифруется часть ассоциатора, содержащая индексы ключевых полей. При шифровании применятся алгоритм, использующий заданный пароль, что ограничивает доступ к данным лиц, имеющих те же программные средства, но не знающих пароль закрытия. Кроме шифрования данных возможно закрыть доступа к таблице паролем для чтения (поиска) или модификации. Последующие операции чтения (поиска) таблицы возможны только при указании пароля доступа на чтение. А операции модификации - еще и пароля доступа на запись.
Прототип:
int HTAPI htTableCreate(
char far *fpTableName, /* Имя таблицы (можно без расширения) */
LPELEMENT fpElems, /* Описатели элементов таблицы */
int nElemCnt, /* Число описателей элементов */
char far *fpCryptoKey, /* Ключ для крипто-закрытия данных */
char far *fpReadPswd, /* Пароль для доступа на чтение */
char far *fpWritePswd, /* Пароль для доступа на запись */
int nOpenMode, /* Режим открытия (константы TAB_???? ) */
LPTHANDLE fpHandle /* Для приема обработчика таблицы */
);
Параметры:
fpTableName
имя файла описания таблицы (с указанием полного или частичного пути), расширение задавать не обязательно
fpElems
задает адрес массива описателей элементов таблицы. Описания производных элементов записи (группы и подстроки) должны располагаться после описания полей. В поле таких элементов указывается:
wOffset
порядковый номер (отсчет от 1) первого поля таблицы, входящего в группу или образующего подстроку
wLength
для группы указывается число смежных полей, образующих группу. Для подстроки содержит смещение подстроки относительно начала образующего поля (отсчет от 1)
cType
Длина подстроки (тип подстроки может быть только ET_CHAR).
nElemCnt
задает число элементов таблицы (размерность массива описателей).
fpCryptoKey
задает строку, используемую в качестве пароля для крипто-закрытия данных. Значащими являются только первые 8 символов. Если пароль не нужен, можно задать NULL или пустую строку "".
fpReadPswd
задает строку, используемую в качестве пароля для доступа к таблице на чтение. Значащими являются только первые 8 символов. Если пароль не нужен, можно задать NULL или пустую строку "".
fpWritePswd
задает строку, используемую в качестве пароля для доступа к таблице на запись. Значащими являются только первые 8 символов. Если пароль не нужен, можно задать NULL или пустую строку "".
nOpenMode
задает флаги открытия ( TAB_??? )
fpHandle
задает адрес переменной для занесения обработчика создаваемой таблицы.
Результат:
0 при успешном завершении
отрицательное число код ошибки
Пример.
Создать таблицу из четырех полей с шифрованием данных и свободным доступом на чтение/запись для локального использования. Кроме полей, таблица будет содержать группу (ключ, объединяющий первые два поля) и подстроку (ключ, состоящий из части второго поля).
/* При создании таблицы смещение полей рассчитывает СУБД */
/* Длина поля имеет смысл только для символьных полей */
ELEMENT asElem[] = {
{ 10, 0, EC_FIELD, ET_CHAR, EK_NOTKEY, "Frst_Name" },
{ 10, 0, EC_FIELD, ET_CHAR, EK_NOTKEY, "Scnd_Name" },
{ 0, 0, EC_FIELD, ET_BYTE, EK_NOTKEY, "Sex" },
{ 0, 0, EC_FIELD, ET_WORD, EK_NOTKEY, "Salary" },
/* Группа, включающая первое и второе имя, образующая ключ */
{ 2, 1, EC_GROUP, ET_CHAR, EK_COMMON, "Name" },
/* Подстрока от второго имени, состоящая из первых пяти символов */
{ 1, 2, EC_SUBSTR, 5, EK_COMMON, "Substr" }
};
THANDLE hNew;
int rc;
rc = htTableCreate( "staff", asElem, sizeof(asElem) / sizeof(ELEMENT),
"password", NULL, NULL, TAB_PRIVATE, &hNew );
if( rc < 0 )
/* Обработка ошибок */
← →
MU © (2005-03-10 09:50) [3]кажется, TElement надо объявить как record
← →
Alexandr3 (2005-03-10 10:08) [4]В описании функции ясно сказано что asElem указатель
на массив описателей элементов таблицы.
Кроме того в примере для Билдера
ELEMENT asElem[] = {
{ 10, 0, EC_FIELD, ET_CHAR, EK_NOTKEY, "Frst_Name" },
{ 10, 0, EC_FIELD, ET_CHAR, EK_NOTKEY, "Scnd_Name" },
{ 0, 0, EC_FIELD, ET_BYTE, EK_NOTKEY, "Sex" },
{ 0, 0, EC_FIELD, ET_WORD, EK_NOTKEY, "Salary" },
/* Группа, включающая первое и второе имя, образующая ключ */
{ 2, 1, EC_GROUP, ET_CHAR, EK_COMMON, "Name" },
/* Подстрока от второго имени, состоящая из первых пяти символов */
{ 1, 2, EC_SUBSTR, 5, EK_COMMON, "Substr" }
};
То же кажется не структура хотя я в си не силен
И вообще не понятно главное почему это срабатывает когда присваивается 5 Элеменов
и сабж раньше первого присваивания когда 6
Еще в одной умной книжке прочитал что перерменной типа вариант нельзя присвоить значение обычного статического массива
а надо использовать VarArrayCreate
Насколько корректно такое объявление
type TElement=array[0..5] of variant;
var
Element:Telement ???
← →
MU © (2005-03-10 10:18) [5]есть ли у вас объявление/описание структуры ELEMENT?
кажется, TElement надо объявить как record
type
TElement = record
wOffset : word;
wLength : word;
cType : byte;
...
end;
var
Elements : array [N..M] of TElement;
← →
Alexandr3 (2005-03-10 10:36) [6]Не понимаю при чем тут запись если в параметры функции
входит int nElemCnt
задает число элементов таблицы (размерность массива описателей).
При предложенном подходе з записью размерность массива всегда будет=1
и вот описание примера для билдера
где тут запись
ELEMENT asElem[] = {
{ 10, 0, EC_FIELD, ET_CHAR, EK_NOTKEY, "Frst_Name" },
{ 10, 0, EC_FIELD, ET_CHAR, EK_NOTKEY, "Scnd_Name" },
{ 0, 0, EC_FIELD, ET_BYTE, EK_NOTKEY, "Sex" },
{ 0, 0, EC_FIELD, ET_WORD, EK_NOTKEY, "Salary" },
/* Группа, включающая первое и второе имя, образующая ключ */
{ 2, 1, EC_GROUP, ET_CHAR, EK_COMMON, "Name" },
/* Подстрока от второго имени, состоящая из первых пяти символов */
{ 1, 2, EC_SUBSTR, 5, EK_COMMON, "Substr" }
};
я вижу массив 6:6
кроме того больше непонятно чем delphi не устраивает добавление одной строки в моем конкретном случае
← →
MU © (2005-03-10 10:56) [7]вот описание ELEMENT (искал за вас...)
http://linux.nist.fss.ru/skaz-mir/doc/v25/local/low/str_ELEMENT.htm
из чего следует, что это структура (record) и передается массив
структур ELEMENT, а не двумерный массив
← →
Alexandr3 (2005-03-10 11:06) [8]Спасибо огромное действительно не доконца прочитал документацию.
← →
icWasya © (2005-03-10 11:23) [9]И не забывать о соглашении о вызовах. Всякие там stdcall, cdecl и иже с ними.
← →
Alexandr3 (2005-03-10 11:23) [10]Все таки не понятно что вызывает Сабж вылетает то он
раньше чем даже инициализируется первый элемент массива
и при 5 элементах не вылетает
← →
Alexandr3 (2005-03-10 11:49) [11]Все таки не понятно что вызывает Сабж вылетает то он
раньше чем даже инициализируется первый элемент массива
и при 5 элементах не вылетает
← →
MU © (2005-03-10 12:01) [12]
> icWasya © (10.03.05 11:23) [9]
> И не забывать о соглашении о вызовах. Всякие там stdcall,
> cdecl и иже с ними
httablecreate:Function(ptablename:Pchar;fpelement:TElement ;nElems:integer;fpCryptoKey:Pchar;fpReadPswd:Pchar;fpWritePswd:Pchar;nOpenMode:integer;fpHandle:THandle):integer; stdcall;
htinit:function(LangRus: pointer;rrr:Integer): integer; stdcall;
← →
Alexandr3 (2005-03-10 12:05) [13]Да про вызовы я понял спасибо
но хотелось бы понять причину сабжа в моем начальном случае я же там ничего не вызываю где этот массив используется только
нtinit
httablecreate закоментированна
← →
MU © (2005-03-10 12:13) [14]htinit:function(LangRus: pointer;rrr:Integer): integer; stdcall;
← →
icWasya © (2005-03-10 12:20) [15]to Alexandr3 (10.03.05 12:05) [13]
> используется только htinit
В Вашем коде htinit описана такhtinit:function(LangRus: pointer;rrr:Integer): integer;
а в DLL скорее всего такint HTAPI htinit(void *LangRus, int rrr);
по этому вызов этой процедуры уже вызовет нарушение стека с непредсказуемым результатом.
← →
Alexandr3 (2005-03-10 12:21) [16]работает конечно спасибо большое
но непонятно что вызывает сабж в чисто теории
если не указывать stdcall;где она передает параметры
и с какая связь между количеством инициализируемых
параметров массива и типом вызова функции
← →
MU © (2005-03-10 12:22) [17]int HTAPI htInit(
LPINIT fpParms, /* Адрес структуры с параметрами */
int nParmLen /* Длина структуры параметров */
);
//
...
int rc;
if( (rc = htInit( NULL, 0 )) < 0 )
{ printf( "Ошибка инициализации HyTech: %s\n", htMessage(rc) );
exit 1;
}
← →
Alexandr3 (2005-03-10 12:33) [18]Где бы подробно почитать про типы вызовов
← →
icWasya © (2005-03-10 18:21) [19]stdcall+F1
ну а по русски так -
в Delphi используются четыре режима передачи параметров
fastcall (по умолчанию), cdecl, stdcall, и safecall
Если используется режим fastcall, (или нет никакого уточнения), то несколько параметров передаются через регистры, остальные грузятся в стек в том порядке, в каком они встречаются в тексте. При выходе из процедуры она сама убирает параметры из стека.
Если используется режим cdecl, (по умолчанию в C/C++) то параметрs грузятся в стек в порядке, обратном тому, в каком они встречаются в тексте. При выходе из процедуры она оставляет параметры в стек.
Если используется режим stdcall, (почти все стандартные API процедуры), то параметры грузятся в стек порядке, обратном тому, в каком они встречаются в тексте. При выходе из процедуры она сама убирает параметры из стека.
Если используется режим safecall, (OLE, COM), то параметры грузятся в стек в том порядке, в каком они встречаются в тексте. При выходе из процедуры она сама убирает параметры из стека.
Обратный порядок загрузки параметров сделан для возможности использовать в C/C++ процедуры с переменным числом параметров.
← →
Набережных С. © (2005-03-10 19:54) [20]
> icWasya © (10.03.05 18:21) [19]
> Если используется режим safecall, (OLE, COM), то параметры
> грузятся в стек в том порядке, в каком они встречаются в
> тексте
Нет, не так. При SafeCall реально используется stdcall.
← →
Anatoly Podgoretsky © (2005-03-10 20:00) [21]icWasya © (10.03.05 18:21) [19]
Интересная у тебя справка.
Alexandr3 (10.03.05 12:33) [18]
Calling Convention
← →
Defunct © (2005-03-11 02:23) [22]Alexandr3 (10.03.05 12:05) [13]
> но хотелось бы понять причину сабжа в моем начальном случае я же там ничего не вызываю где этот массив используется только
Причина проста как мир. Вы компилировали с выключенным Range Check. Поскольку httablecreate располагалась непосредственно за Element, и вы получали адрес httablecreate до заполнения структуры Element, то нормально полученный адрес httablecreate затирался какой-то чипухой на строке Element[5]:= "First_Name";
могу поспорить, что если бы в вашем изначальном коде
Element:TElement;
httablecreate:Function
между объявлениями Element и httablecreate было бы что-то eще, AV вы бы не получили, и маялись бы в поисках ошибки гораздо дольше:
Element:TElement;
TempSpace: Array[1..10000] of byte;
httablecreate:Function;
← →
icWasya © (2005-03-11 12:47) [23]to Anatoly Podgoretsky © (10.03.05 20:00) [21]
>Интересная у тебя справка.
Это я по памяти. А так Вы правы.
должно быть так
Если используется режим pascal, то параметры грузятся в стек в том порядке, в каком они встречаются в тексте. При выходе из процедуры она сама убирает параметры из стека. Используется для совместимости со старыми программами.
safecall - с параметрами то же что и stdcall , плюс специальный механизм обработки исключений для OLE/COM
Страницы: 1 вся ветка
Форум: "Основная";
Текущий архив: 2005.03.27;
Скачать: [xml.tar.bz2];
Память: 0.53 MB
Время: 0.038 c