Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 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.54 MB
Время: 0.036 c
6-1138639504
parovoZZ
2006-01-30 19:45
2006.06.04
Кнопка и TWebBrowser


2-1148038893
ttt_111
2006-05-19 15:41
2006.06.04
Работа с БД.


3-1142429352
Emik
2006-03-15 16:29
2006.06.04
FIBPlus Tools


2-1147375848
SmallCod
2006-05-11 23:30
2006.06.04
Сетка участников соревнований


15-1147168601
Kolan
2006-05-09 13:56
2006.06.04
Где взять описание языка UML





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский