Форум программистов, компьютерный форум, киберфорум
Наши страницы
Delphi для начинающих
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.88/17: Рейтинг темы: голосов - 17, средняя оценка - 4.88
Konctantin
939 / 743 / 170
Регистрация: 12.04.2009
Сообщений: 1,700
1

Вызов функции через GetProcAddress и передача ей параметров

03.09.2013, 12:18. Просмотров 3217. Ответов 13
Метки нет (Все метки)

Доброго времени суток, еще раз хочу задать (может быть для кого и нубский) вопрос.
Суть в следующем:
для того чтобы вызвать функцию из ДЛЛ можно использовать такой код
Pascal
1
2
3
4
5
6
7
8
9
type
TFunc = function(connection_str : string; id : integer) : integer;
...
var
mFunc: TFunc;
dllInstance := LoadLibrary(dllName);
@mFunc:= GetProcAddress(dllInstance, funcName);
...
mFunc('connstr', 123);
ну это и так понятно, а вот как быть, чтобы вызывать функцию без ее определения.

к примеру, у меня есть какой-то метод/класс в котором происходит обработка запуска функций из dll'ок
там много кода бла бла для обработки самих вызовов.

так вот есть к примеру функция вида
Pascal
1
function (dllName, funcName : string; const Args: array of const);
тобиш в функцию я передаю имя dll, имя функции и параметры которые нужно передать вызываемой функции.
при этом параметры в dll'ках фиксированные.


как такое реализовать в дельфи? или без asm вставок не обойтись?
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
03.09.2013, 12:18
Ответы с готовыми решениями:

Передача параметров через список параметров формы
Hi all! У кого есть опыт передачи параметров через заголовочный список...

Как работает передача параметров в функции и почему?
function a_plus_b(a: integer; var b: integer): integer; begin Result:=a+b;...

Вызов функции через определенные интервалы времени
Здравствуйте подскажите как сделать запуск имени ф-ции каждые N минут?

Передача параметров
День добрый! Подскажите как из формы авторизации передать в главную форму...

Передача параметров в процедуру
Есть класс формы, я прописал процедуру для редактирования формы, но передать в...

13
mss
2632 / 2257 / 275
Регистрация: 24.12.2010
Сообщений: 13,725
03.09.2013, 23:43 2
Цитата Сообщение от Konctantin Посмотреть сообщение
параметры в dll'ках фиксированные
"фиксированные" - это как ?
1
Konctantin
939 / 743 / 170
Регистрация: 12.04.2009
Сообщений: 1,700
04.09.2013, 01:13  [ТС] 3
ну не (const Args: array of const) а (param1, param2 : integer; str : string)
0
mss
2632 / 2257 / 275
Регистрация: 24.12.2010
Сообщений: 13,725
04.09.2013, 09:16 4
Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
type
TFunc = function(param1, param2 : integer; str : string) : integer;
...
 
function (dllName, funcName : string; param1, param2 : integer; str : string): integer;
var
  mFunc: TFunc;
begin
  dllInstance := LoadLibrary(dllName);
  mFunc:= GetProcAddress(dllInstance, funcName);
  Assert(@mFunc <> 0);
  Result := mFunc(param1, param2, str);
end;
1
Konctantin
939 / 743 / 170
Регистрация: 12.04.2009
Сообщений: 1,700
04.09.2013, 18:59  [ТС] 5
и чем это отличается от того что в первом посте?
0
FIL
Модератор
3419 / 2555 / 726
Регистрация: 19.09.2012
Сообщений: 7,923
04.09.2013, 19:15 6
Konctantin, объясни еще раз, что ты хочешь сделать.
1
mss
2632 / 2257 / 275
Регистрация: 24.12.2010
Сообщений: 13,725
05.09.2013, 10:02 7
Цитата Сообщение от Konctantin Посмотреть сообщение
чем это отличается от того что в первом посте?
Теми самыми "фиксированными параметрами"
1
Konctantin
939 / 743 / 170
Регистрация: 12.04.2009
Сообщений: 1,700
05.09.2013, 12:13  [ТС] 8
Возможно я некорректно выразился, попробую поподробней:
И так есть несколько ДЛЛок, которые писались разными людьми, у них есть функции, которые просто запускают отчеты.
но параметры этих функций разные.

в основном модуле идет вызов этих функций, но сейчас это унылое зрелище (не знаю как и кто то писал).
для того чтобы вызвать одну функцию при человек писал код вызова (40-100 строк) + код освобождения (20+ строк).
А теперь представьте себе, что таких ДЛЛок около 10 и в каждой около 20-50 таких функций, и еще представьте что творится в основном модуле из-за этого.

Сейчас я занимаюсь рефакторингом и частичным портированием (С# с дальнейшим переходом) этого все дела.
С дельфи я знаком поверхностно и не испытываю особого удовольствия от кодинга на нем. Но тем не мене хочется упростить этот код и убрать мусор.

так вот. Я написал класс через который хотел вызывать эти функции, в нем идет регистрация ДЛЛки (чтобы повторно не создавать указатель на нее) и очистка. Но вот вызовы я хотел делать через одну функцию, передавая параметры в виде массива, а потом подставлять эти параметры для вызываемой функции из ДЛЛок.
как-то так:
Pascal
1
function (dllName, funcName : string; const Args: array of const);
в общем суть заключается в том, чтобы раскрутить параметры из Args в перечень параметров для вызываемой функции.

могу сказать только то, что все параметры являются указателем на строку либо числом.

Переписать все ДЛЛки под какой-то стандарт не является возможным.

ЗЫ. тестировал вариант с asm вставкой, и последующим занесением всего этого дела в стек а потом call funcAddr, но такое стремно ставить, так как нет уверенности в корректности его работы.

На C# я подобное сделал с помощью ILGenerator (скорость вызова не критична). А вот в дельфи не знаю как поступить. Но если это получится, основной модуль упростится на ~2000 строк кода.
0
murderer
3319 / 1465 / 134
Регистрация: 06.10.2010
Сообщений: 3,217
05.09.2013, 13:18 9
код вызова (40-100 строк) + код освобождения (20+ строк).
Прилинкуй статически
Delphi
1
function(connection_str : string; id : integer) : integer;external 'dllname';
частичным портированием (С# с дальнейшим переходом)
С# поддерживает pascal-строки и соглашение register? Или ты хочешь написать враппер для всей этой кучи dll в виде одной dll на асме и вызывать по соглашению stdcall, а внутри переводить нульзавершённые строки в pascal-string?

Добавлено через 14 минут
Ещё важно знать версию Delphi (в частности string - это AnsiString или WideString).
1
Konctantin
939 / 743 / 170
Регистрация: 12.04.2009
Сообщений: 1,700
05.09.2013, 13:45  [ТС] 10
Прилинкуй статически
по некоторым причинам это невозможно.
С# поддерживает pascal-строки и соглашение register?
для этого есть маршалинг
Ещё важно знать версию Delphi (в частности string - это AnsiString или WideString).
Юникод поддерживается string - WideString
Или ты хочешь написать враппер для всей этой кучи dll в виде одной dll на асме и вызывать по соглашению stdcall
именно, только не хотелось бы использовать асм вставки для этого.
Есть ли какой-то способ управлять стеком в дельфи?
0
murderer
3319 / 1465 / 134
Регистрация: 06.10.2010
Сообщений: 3,217
05.09.2013, 14:29 11
Без асма не знаю как. Попробуй пока это, потом можно будет немного оптимизировать. Тут отсутствует проверка на количество параметров - их должно быть не менее 3.
Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
function Wrapper(dllName, funcName : PAnsiChar; params: array of Variant): integer;stdcall;
var
  mFunc:       pointer;
  dllInstance: THandle;
begin
  dllInstance:=LoadLibraryA(dllName);
  mFunc:=GetProcAddress(dllInstance, funcName);
  asm
  pushad
  mov  ebx,[params]
  mov  ecx,[ebp+$14]
  inc  ecx                //Длина массива (количество элементов)
  shl  ecx,4              //Длина массива в байтах
  add  ebx,ecx
  neg  ecx
  mov  esi,esp
  @2:push [ebx+ecx+8]
     add  ecx,16
  jnz @2
  mov  eax,[esi-4]        //Первые 3 параметра передаются через eax,edx,ecx
  mov  edx,[esi-8]
  mov  ecx,[esi-12]
  call [mFunc]
  add  esp,12
  mov  [result],eax
  popad
  end;
  FreeLibrary(dllInstance);
end;
Добавлено через 3 минуты
Если есть возможность перекомпилировать dll, то можно и без асма - просто объявляешь их как cdecl varargs и все параметры делаешь опциональными.
1
mss
2632 / 2257 / 275
Регистрация: 24.12.2010
Сообщений: 13,725
05.09.2013, 16:06 12
Konctantin, вот эта трава может оказаться подходящей
1
Konctantin
939 / 743 / 170
Регистрация: 12.04.2009
Сообщений: 1,700
06.09.2013, 11:18  [ТС] 13
Спасибо за подсказки, но как оказалось, к сожаленью, но тип PChar (и ему подобные) не преобразуется в Variant.
(может я чего-то и не знаю, так как с дельфи не сильно знаком).

но в итоге сделал так:
создал несколько прототипов функций вида (благо больше 10 параметров никто не передавал, а в будущем договорились о более стандартизированном наборе параметров),
Pascal
1
2
3
4
5
function() : LongInt;
function<T>(p1:T) : LongInt;
function<T1,T2>(p1:T1;p2:T2) : LongInt;
function<T1,T2,T3>(p1:T1;p2:T2;p3:T3) : LongInt;
// и т.д.
в общем с использованием сего дела, мне удалось сократить размер юнита на ~2500 строк кода (еще не все переделал).
Читабельность тоже вроде бы улучшилась.

Более того, я напичкал Unit DllWrapper всяческими проверками что сразу дало мне контроль над запуском Dll'ок.

ЗЫ. Следующая ступень рефакторинга - разбитие на модули и применение ООП (так как написано все процедурно).
А потом постепенное подключение этих модулей к проекту на C# (там все сделано как надо), и постепенное "удаление в корзину старого проэкта".

ЗЫЫ. главное чтобы это был безболезненный и незаметный переход для клиентов.

Еще раз всем спасибо.
0
murderer
3319 / 1465 / 134
Регистрация: 06.10.2010
Сообщений: 3,217
06.09.2013, 12:51 14
к сожаленью, но тип PChar (и ему подобные) не преобразуется в Variant.
Variant-строки - это тоже самое, что и WideString. То есть это указатель на первый символ, а по смещению (-4) хранится длина строки в байтах.
0
06.09.2013, 12:51
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
06.09.2013, 12:51

Передача параметров в программу
Как сделать чтобы программа могла принимать входящие параметры? и как мне...

Передача параметров в процедуру
В приложении динамически создается объект(не суть важно какой) для обработки...

Передача параметров из командной строки
Всем доброго дня. Сразу скажу, что в Делфи новичок. Помогите с таким...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
14
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2018, vBulletin Solutions, Inc.
Рейтинг@Mail.ru