Форум: "Основная";
Текущий архив: 2006.06.04;
Скачать: [xml.tar.bz2];
ВнизИмпорт функций из сишной DLL... Вроде все просто, а не работает. Найти похожие ветки
← →
Deka © (2006-04-26 16:39) [0]
procedure TTestForm.Button1Click(Sender: TObject);
var
HD: HModule;
FI: function(): Cardinal; stdcall;
FC: function(var Number: Cardinal): Cardinal; stdcall;
NN: Cardinal;
begin
HD:= LoadLibrary("RyeDLL.dll");
try
If HD <> 0 then begin
FI:= GetProcAddress(HD, "InitControl");
If Assigned(FI) then begin
FI; // Это работает
FC:= GetProcAddress(HD, "Connect");
If Assigned(FC) then begin
NN:= 0;
FC(NN); // А это не работает
end;
end;
end;
finally
FreeLibrary(HD);
end;
end;
Из файла RyeDll.h
RYEDLL_API LONG32 InitControl();
RYEDLL_API LONG32 Connect(LONG32 nCamNum);
Ошибка (акцесс виолэйшн) возникает в строкеFC(NN);
в модуле ntdll.dll
Подскажите что не так? Подозреваю, что что-то с передачей параметров, но что точно - не знаю.
← →
SuperBUG © (2006-04-26 17:02) [1]не совсем в тему,но LONG32-32-bit signed integer
Cardinal-unsigned 32 bit
судя по тому что происходит вызов и в первом случае ошибки нет а во втором в наличии есть cмысл поиграться с calling convetion,например попробовать вместо stdcall cdecl
← →
MBo © (2006-04-26 17:20) [2]RYEDLL_API - посмотри определение
← →
Deka © (2006-04-26 17:49) [3][1] Сделал так:
procedure TTestForm.Button5Click(Sender: TObject);
var
HD: HModule;
FI: function(): LongInt; stdcall;
FC: function(var Number: LongInt): LongInt; cdecl;
NN: LongInt;
begin
HD:= LoadLibrary("RyeDLL.dll");
try
If HD <> 0 then begin
FI:= GetProcAddress(HD, "InitControl");
If Assigned(FI) then begin
FI;
FC:= GetProcAddress(HD, "Connect");
If Assigned(FC) then begin
NN:= 0;
FC(NN);
end;
end;
end;
finally
FreeLibrary(HD);
end;
end;
- Таже ошибка.
[2] - Что есть определение?
P.S. Ну не шарю я в Си!
← →
Deka © (2006-04-26 17:50) [4][3] Это вот это?
#define RYEDLL_API __declspec(dllexport)
← →
MBo © (2006-04-26 17:57) [5]stdcall должно быть, а не cdecl
Connect(LONG32 nCamNum) - передача параметра по значению, а не по ссылке, так что var убери
FC: function(Number: Integer): Integer; stdcall;
← →
Cashmare © (2006-04-26 18:10) [6]MBo © (26.04.06 17:57) [5]
stdcall должно быть, а не cdecl
Я долго писал stdcall на сишные функции, пока не столкнулся с количеством вызова сишной функции по многу миллионов раз (в отдельном потоке) за время выполнения программы. Через некоторое время работы прога падала из-за переполнения стека. После замены stdcall на cdecl все стало нормально работать. Наверно, я чего-то не понимаю...
← →
MBo © (2006-04-26 18:15) [7]>Cashmare
сишные функции, экспортируемые из DLL, могут быть с разными соглашениями о вызове - конкретное соглашение для каждой функции описано в заголовочном файле.
А просто от фонаря ставить соглашение - мягко говоря, не выход...
← →
Deka © (2006-04-27 09:16) [8]Как я только не ставил... и var... и const... и вообще без ничего - не работает. Любому человеку который сможет экспортировать функции из RyeDLL.dll подарю SDK для управления фотоаппаратами Olympus. Собственно из этого SDK и библиотека. Есть пример использования этой библиотеки на C. полное описание и все необходимое для сборки проектов с использованием этой библиотеки в сишных проектах.
P.S. Соглашения о вызовах тоже все перепробовал...
← →
evvcom © (2006-04-27 11:23) [9]Даже перебрав все комбинации, нельзя быть уверенным, что все ок. Надо наверняка. Ну шли эту dll мне на мыло, ИДА-шкой посмотрю, что там. Имя функции Connect? Надеюсь, она небольшая?
← →
Deka © (2006-04-27 11:38) [10]Ок. Спасибо. Отправил. Имя функции Connect. Надеюсь с остальными проблем не будет (с остальными функциями). Просто Connect ключевая - подключение к фотоаппарату.
← →
evvcom © (2006-04-27 12:28) [11]IDA определил ее как
int __cdecl Connect(int);
т.е. соглашение однозначно поставить cdecl. Определить характер параметра не удалось, т.к. из Connect вызывается другая функция, адрес которой берется из глобальной переменной и рассчитывается где-то раньше. Но судя по "LONG32 nCamNum" можно поставить Integer по значению. Что возвращает, тоже определяется в вызываемой функции.
В дельфи:
type
TFunConnect = function(Number: Longint): Longint; cdecl;
Если не работает, то дай угадаю. AV по адресу 0000000C. Правильно? Значит эта самая глобальная переменная не инициализирована. Смотри документацию, как ты должен перед коннектом инициализировать. Хотя, если говоришь, что InitControl работает... Она тоже из той же глобальной переменной данные берет.
Попробуй посмотреть отладчиком в CPU Window.
← →
han_malign © (2006-04-27 12:37) [12]>AV по адресу 0000000C. Правильно? Значит эта самая глобальная переменная не инициализирована.
- а я бы еще посмотрел что возвращает - InitControl.
Наверняка ведь ошибку...
← →
Deka © (2006-04-27 12:42) [13]AV по адресу 0000000C. Правильно. Инициализация перед Connect сводится к вызову InitControl, который невозвращает ошибок. Т.е. инициализация проходит успешно. Попробовал с другой функцией из библиотеки, не требующей установки связи с камерой. Получение числа обнаруженных камер - все работает. Функция коректно вызывается, завершается и дает правильный результат.
← →
Deka © (2006-04-27 12:49) [14]Незнаю что я изменил, но сейчас вроде заработало. А менял я много чего. посмотрим дальше... Всем спасибо, особенно evvcom. Если нужен приз - пиши.
← →
Deka © (2006-04-27 12:54) [15]Возможно инициализация глобальной переменной прошла после запроса числа найденных камер.
Вот как это выглядит:
FN:= GetProcAddress(HD, "GetPropCameraCount");
If Assigned(FN) then begin
ShowMessage("Всего камер " + IntToStr(FN));
end;
Ну и объявление процедуры выполнено как в [11]
Кривая какая-то библиотека!
← →
Сергей М. © (2006-04-27 13:01) [16]
> Deka © (27.04.06 12:54) [15]
С какого это перепугу переменная FN в результате вызова GetProcAddress получила значение, равное числу камер ?
Число камер возвратит ф-ция GetPropCameraCount, которую ты на момент ShowMessage еще не вызывал.
← →
Сергей М. © (2006-04-27 13:02) [17]Извиняюсь, что-то я притормозил - обращение к FN и есть вызов ф-ции GetPropCameraCount
← →
Сергей М. © (2006-04-27 13:04) [18]
> Deka © (27.04.06 12:54) [15]
А в документации к библ-ке нет ли каких-либо упоминаний об асинхронности работы тех или иных эксп.вызовов ?
← →
evvcom © (2006-04-27 13:04) [19]Приз... :) Камеры олимпуса у меня нет. Если только бутылочку пивка! :) Но пока она дойдет из Геленджика... совсем теплая будет. :-)
← →
han_malign © (2006-04-27 13:13) [20]>Если нужен приз - пиши.
http://hard1ock.narod.ru/
← →
evvcom © (2006-04-27 13:15) [21]
> Возможно инициализация глобальной переменной прошла после
> запроса числа найденных камер.
Нет. GetPropCameraCount тоже считает адрес от той глобальной переменной. Видимо, вызов InitControl у тебя проходил неудачно и в результате затирал ту переменную. Может камера была не подключена, может еще что-то. Прав
> han_malign © (27.04.06 12:37) [12]
Надо анализировать результат InitControl. Видимо, переменная инициализируется при загрузке библиотеки, а потом в случае ошибки обниливается, и дальнейшая работа библиотеки невозможна без ее перезагрузки.
← →
evvcom © (2006-04-27 13:27) [22]Посмотри еще функцию CameraReady(int). Возможно, ее нужно вызывать для проверки готовности камеры перед InitControl.
← →
han_malign © (2006-04-27 13:31) [23]>Надо анализировать результат InitControl.
- кстати по всем FAQ четко прослеживается что InitControl можно вызывать только один раз...
а GetPropCameraCount - по идее, инициализирует спосок устройств, к которомы ты пытаешся пробиться с Connect...
З.Ы. Модератору - сылочку, по уму, надо бы прибить, т.к. нарушение авторских прав(погорячился), да и ссылки там битые. Правда на правильные ссылки можно выйти простеньким запросом на yandex-е(Google - пасует).
З.З.Ы. Интересно является ли нарушением авторских прав импортирование tlib для ActiveX, который в RyeDLL.dll лежит?
← →
evvcom © (2006-04-27 13:46) [24]
> импортирование tlib для ActiveX, который в RyeDLL.dll лежит
Что-то я там не увидел tlib. Только информация о версии. Может версии dll разные (1.3, 1.4)?
> а GetPropCameraCount - по идее, инициализирует спосок устройств
Фиг знает, чего она там инициализирует, но из себя вызывает другую функцию, адрес которой также вычисляется от глобальной переменной, которая оказалась у автора затертой после вызова InitControl. Так что...
← →
Deka © (2006-04-27 13:47) [25]Да. InitControl вызывается только один раз. А с призом смешно получилось. Извините и спасибо за помощь.
Только что провел простой эксперимент - убрал запрос числа подключенных камер перед обращением к Connect - получил AV. Так что НАДО сперва запросить число подключенных камер.
← →
evvcom © (2006-04-27 13:52) [26]
> убрал запрос числа подключенных камер перед обращением к
> Connect - получил AV
Значит
> дай угадаю. AV по адресу 0000000C.
адрес - чистое совпадение. Видимо, вызов происходит, а дальше где-то еще есть место с потенциальным чтением с адреса 0000000C
← →
Сергей М. © (2006-04-27 14:02) [27]
> Так что НАДО сперва запросить число подключенных камер
Одно из двух - то ли невнимательное чтение док-ции производителя того самого ПО, то ли это самое ПО следует выкинуть в мусор.
← →
isasa © (2006-04-27 15:06) [28]Я, конечно, извиняюсь, но везде звучит как,
[code]
FI: function(): Cardinal; stdcall;
FC: function(var Number: Cardinal): Cardinal; stdcall;
...
[b]@FI:= GetProcAddress(HD, "InitControl");[/b]
...
[b]@FC:= GetProcAddress(HD, "Connect");[/b]
[code]
← →
isasa © (2006-04-27 15:08) [29]Сорри. В Opera v 8.54, напрочь, кнопки не работают :(
← →
evvcom © (2006-04-27 15:19) [30]
> FI: function(): Cardinal; stdcall;
это еще пройдет, так как параметров нет и стек чистить не надо.
> FC: function(var Number: Cardinal): Cardinal; stdcall;
А вот здесь словишь ошибку, так как функция в dll не будет чистить стек, потому как она так написана (cdecl), а вызывающая сторона не будет чистить, потому как будет думать, что он уже почищен. В результате в скором времени словишь исключение, скорее всего AV.
← →
evvcom © (2006-04-27 15:20) [31]Скорое время = несколько команд процессора.
← →
Deka © (2006-04-27 16:10) [32]Интересно, почему игнорируется пост №3? Там уже исправлены соглашения вызовов для критической функции. Да и вообще я уже написал что ПРОБЛЕМА РЕШЕНА. Во всяком случае буду искать следующую ошибку. В документации необходимая последовательность вызовов не описана. Все что есть, это "Вызовите один раз перед началом всех операций с камерой InitControl". Про то, что надо вызвать вторую функцию для корректной работы нет ни слова. Конечно по идее надо выполнить элементарную проверку на присутствие камер при помощи вызова функции определения их числа и наверное на это рассчитывал автор DSK, НО как я понимаю, с его стороны это является ошибкой, так как нет указания на эту "фишку".
Всем спасибо.
Страницы: 1 вся ветка
Форум: "Основная";
Текущий архив: 2006.06.04;
Скачать: [xml.tar.bz2];
Память: 0.53 MB
Время: 0.042 c