Конференция "WinAPI" » Динамическая загрузка DLL
 
  • Vidog © (30.11.10 19:04) [0]
    Здравствуйте.

    Хочется узнать, есть ли способ получить список всех export'нутых функций и процедур из DLL и списком параметров к ним с указанием типа параметра + тип результата функции.

    Например:

    type
     TDLLFunctionParam = record
       Name: String;
       pType: String;
     end;

     TDLLFunctionParams = array of TDLLFunctionParam;

     TDLLFunction = record
       Name: String;
       Params: TDLLFunctionParams;
       Result: TDLLFunctionParam;
     end;

     TDLLFunctions = array of TDLLFunction;

    var
    h: HWND;
    fs: TDLLFunctions;
    begin
    h := LoadLibrary('C:\mylib.dll');
    fs := getLibraryFunctions(h);
    end;



    и затем вызвать любую функцию и получить результат:


    var
    h: HWND;
    fs: TDLLFunctions;
    f: TDLLFunction;
    s: String;
    begin
     h := LoadLibrary('C:\mylib.dll');
     fs := getLibraryFunctions(h);
     f := fs[0];
     s := callLibraryFunction(h, f, ['a', '1', '1.2']);
    end;



    то есть я передаю handle библиотеки, функцию и массив строковых параметров, получаю строковой результат в S

    Или нужно заранее знать имена всех функций и четко предопределять параметры?
    Вызывая GetProcAddress(Module: THandle; ProcName: PChar);
  • Игорь Шевченко © (30.11.10 20:05) [1]

    > Или нужно заранее знать имена всех функций и четко предопределять
    > параметры?


    да
  • Vidog © (30.11.10 20:34) [2]
    А если я заведомо знаю имена функций и кол-во параметров, функцию braryFunction(h, f, ['a', '1', '1.2']); можно будет использовать?.. Или я пролетел вообще?)
  • Leonid Troyanovsky © (30.11.10 21:27) [3]

    > Vidog ©   (30.11.10 20:34) [2]

    > А если я заведомо знаю имена функций и кол-во параметров,
    >  функцию braryFunction(h, f, ['a', '1', '1.2']); можно будет
    > использовать?.. Или я пролетел вообще?)

    А с какого вдруг пуркуа длл?

    See also: varargs directive.

    --
    Regards, LVT.
  • Игорь Шевченко © (01.12.10 00:34) [4]

    > А если я заведомо знаю имена функций и кол-во параметров,
    >  функцию braryFunction(h, f, ['a', '1', '1.2']); можно будет
    > использовать?.. Или я пролетел вообще?)


    можно
  • Vidog © (01.12.10 22:02) [5]
    2 Игорь Шевченко
    >>можно

    подскажите, пожалуйста.
  • Leonid Troyanovsky © (01.12.10 23:02) [6]

    > Vidog ©   (01.12.10 22:02) [5]

    > подскажите, пожалуйста.

    Готов подсказать, если пользование длл обоснованно.

    --
    Regards, LVT.
  • Игорь Шевченко © (02.12.10 10:13) [7]

    > подскажите, пожалуйста.


    что подсказать ?
  • Vidog © (02.12.10 18:20) [8]

    > что подсказать ?


    каким образом можно реализовать вот это:
    s := callLibraryFunction(h, f, ['a', '1', '1.2']);


    из части кода. желательно на WinAPI. Куда копать, что почитать :)
  • Игорь Шевченко © (02.12.10 18:31) [9]

    > из части кода. желательно на WinAPI. Куда копать, что почитать
    > :)


    http://www.delphi-jedi.org раздел API Tranlsation
    например почитать
  • Vidog © (02.12.10 20:47) [10]
    >>dlopen
    я в ту сторону копаю?)
  • Vidog © (02.12.10 20:47) [11]

    > http://www.delphi-jedi.org раздел API Tranlsation например
    > почитать

    Спасибо большое за информацию.
  • Vidog © (02.12.10 21:06) [12]

    function test(a, b, c: String): String;
    begin
     Result := '[' + a + ']' + '[' + b + ']' + '[' + c + ']';
    end;

    exports test;



    Вот такая в DLL тестовая функция с 3мя параметрами.


    var
     modl: TModuleHandle;
     P: Pointer;
     S: String;
    begin
     LoadModule(modl, 'Project1.dll');
     P := GetModuleSymbol(modl, 'test');
     S := 'qwe-qwe-qwe';
     WriteModuleData(modl, 'test', S, sizeOf(S));
    end;



    насколько я понял, передать данные можно через WriteModuleData, а прочитать потом через ReadModuleData.

    Так вот.. Каким образом передать 3 параметра? Выполнить функцию 3 раза? Каждый раз записывая параметр. Или я вообще не туда полез...
  • Сергей М. © (02.12.10 23:25) [13]

    > LoadModule


    > WriteModuleData


    Это вообще из какой оперы ?
  • Vidog © (03.12.10 09:48) [14]

    > Это вообще из какой оперы ?


    moduleloader.pas

    =/ что-то у меня ничего не получается...
  • Leonid Troyanovsky © (03.12.10 17:54) [15]

    > Vidog ©   (03.12.10 09:48) [14]

    Что ты испод нас хочешь?

    --
    Regards, LVT.
  • Сергей М. © (03.12.10 20:49) [16]

    > Vidog ©   (03.12.10 09:48) [14]
    >
    >
    > > Это вообще из какой оперы ?
    >
    >
    > moduleloader.pas
    >


    Какой еще нахрен "moduleloader.pas" ?
    Нет такого юнита в составе штатных дельфийских юнитов.
    По кр.мере - в Д7.
  • Leonid Troyanovsky © (03.12.10 22:42) [17]

    > Сергей М. ©   (03.12.10 20:49) [16]

    > Какой еще нахрен "moduleloader.pas" ?

    М.б. by JEDI?

    Хотя, конечно, проще отрубить ему голову.

    --
    Regards, LVT.
  • Vidog © (05.12.10 22:23) [18]

    > Какой еще нахрен "moduleloader.pas" ?


    из JEDI библиотеки..

    Мужики, ну спасайте) Дайте хоть ссылочку на пример или какие использовать модули / функции.
  • Сергей М. © (05.12.10 23:28) [19]

    > Vidog ©   (05.12.10 22:23) [18]


    Посмотрел.

    Этот самый moduleoader не имеет никакого отношения к тому что тебе нужно.

    А то что тебе нужно, т.е.

    > спискоr параметров к ним с указанием типа параметра + тип результата функции

    гарантированно на 100% в ран-тайм можно получить только в отдельных частных случаях. В прочих случаях, не относящихся к этим самым "частным", задача в ран-тайм практически не решаема.
  • Vidog © (06.12.10 00:12) [20]

    > function test(a, b, c: String): String;
    > begin
    >   Result :=  '[' + a + ']' + '[' + b + ']' + '[' + c + ']';
    > end;
    > exports test;


    а конкретно в таком случае? без определения этой функции и получения ее адреса с последующим вызовом, можно передать ей параметры "на лету" и забрать результат?
  • Германн © (06.12.10 00:26) [21]

    > а конкретно в таком случае?

    <offtop>
     Твой вопрос сильно смахивает на задачу/вопрос XYZ http://www.gunsmoker.ru/2008/10/x-y-z.html
    </offtop>
    Сам подумай кому нужно ломать голову над некой тестовой функцией, которая не имеет никакого смысла для отвечающих?


    > Мужики, ну спасайте

    Пока не озвучишь свою реальную задачу, на реальную помощь не надейся.
  • Anatoly Podgoretsky © (06.12.10 09:05) [22]
    лучше отрубить голову.
  • Сергей М. © (06.12.10 20:43) [23]

    > а конкретно в таком случае?


    А чем этот "конкретно такой случай" отличается от "неконкретно хз какого случая" ?
  • Игорь Шевченко © (06.12.10 23:14) [24]
    rundll как-то работает. Загружает DLL, ищет в ней функцию с указанным именем, преобразует параметры из строк в числа или в строки, передает эти параметры и вызывает нужную функцию.

    Автору наверное надо что-то похожее.
  • Германн © (07.12.10 04:08) [25]

    > Игорь Шевченко ©   (06.12.10 23:14) [24]
    >
    > rundll как-то работает

    Вот-вот. Как rundl работает?
    "Загружает DLL, ищет в ней функцию с указанным именем, преобразует параметры из строк в числа или в строки, передает эти параметры и вызывает нужную функцию". Не верю.
  • Ой (07.12.10 10:29) [26]
    +1
    А если Dll C'ишная...? Это бред. ))
  • Leonid Troyanovsky © (07.12.10 16:08) [27]

    > Германн ©   (07.12.10 04:08) [25]

    > Вот-вот. Как rundl работает?

    Чему ты не веришь?
    Функции, которые она вызывает имеют прототип:

    procedure X( wnd: HWND;
                     hinst: THandle;
                     CmdLine: PChar;
                     nCmdShow: Longint);  stdcall;
    Х должна быть в экспортах.

    А rundll, получив строку, должна выделить (и преобразовать)
    3 числа и строку параметров.

    --
    Regards, LVT.
  • Сергей М. © (07.12.10 19:33) [28]

    > Автору наверное надо что-то похожее


    Было бы "надо" - он бы сказал.
    А он, похоже, даже своё "надо" в лицо не знает. Но при этом ему "хочется". А что ему "хочется" - это он уточнять не намерен)
  • Leonid Troyanovsky © (07.12.10 22:56) [29]

    > Сергей М. ©   (07.12.10 19:33) [28]

    > ему "хочется". А что ему "хочется" - это он уточнять не
    > намерен)

    Ему хочется странного, потому древние китайцы
    ему голову и постановили элиминировать.

    --
    Regards, LVT.
  • Сергей М. © (07.12.10 23:29) [30]

    > Leonid Troyanovsky ©   (07.12.10 22:56) [29]


    Кошмар, конечно, но.. с древнекитайскими традициями вряд ли поспоришь) .. особливо здесь, в Мастерской)
  • Leonid Troyanovsky © (07.12.10 23:40) [31]

    > Сергей М. ©   (07.12.10 23:29) [30]

    > Кошмар, конечно, но.. с древнекитайскими традициями вряд
    > ли поспоришь) .. особливо здесь, в Мастерской)

    А в Детской рискнешь? :)

    --
    Regards, LVT.
  • Сергей М. © (08.12.10 00:18) [32]

    > Leonid Troyanovsky ©   (07.12.10 23:40) [31]


    > в Детской рискнешь? :)


    В детской тем паче не рискну)
  • Германн © (08.12.10 02:01) [33]

    > Leonid Troyanovsky ©   (07.12.10 16:08) [27]
    >
    >
    > > Германн ©   (07.12.10 04:08) [25]
    >
    > > Вот-вот. Как rundl работает?
    >
    > Чему ты не веришь?
    > Функции, которые она вызывает имеют прототип:
    >

    Не верю в реальность вызова произвольной функции из произвольной библиотеки а-ля rundll.
    А все остальное - к автору вопроса.
    С учётом Германн ©   (06.12.10 00:26) [21]
  • Leonid Troyanovsky © (08.12.10 08:20) [34]

    > Германн ©   (08.12.10 02:01) [33]

    > Не верю в реальность вызова произвольной функции из произвольной
    > библиотеки а-ля rundll.

    Произвольной - я тоже не верю.

    http://support.microsoft.com/kb/164787

    Про 3 числа я не совсем верно сказал,
    только параметры, sorry.

    --
    Regards, LVT.
  • Vidog © (09.12.10 17:29) [35]

    >  [24]
    > rundll как-то работает. Загружает DLL, ищет в ней функцию
    > с указанным именем, преобразует параметры из строк в числа
    > или в строки, передает эти параметры и вызывает нужную функцию.
    > Автору наверное надо что-то похожее.


    Да. именно это и нужно.

    Я пытаюсь создать так называемую систему "плагинов" к приложению. Как например модули DLL для php. Все функции экспортнуты внутри DLL, число параметров, допустим, будет известно, имена функций тоже.

    плагин к lister'у тотал-коммандера умеет находить в любой библиотеке функции, которые были объявлены на export. И даже запускать процедуры (без параметров).

    Поэтому заранее предопределить вызовы внутри приложения не получится. Они переменны и в каждой DLL будут уникальны.
  • Сергей М. © (09.12.10 21:33) [36]

    > Как например модули DLL для php


    Те же самые "модули DLL для php" - вполне документированная спецификация и технология, безо всякого бардака типа "на вот тебе модуль, в нем заранее неопределенная хуча экспортнутых точек входа, а их параметры выковыривай сам если тебе приспичило ".

    Так что это сравнение - в топку.
  • Германн © (10.12.10 01:40) [37]

    > Все функции экспортнуты внутри DLL, число параметров, допустим,
    >  будет известно, имена функций тоже.


    > Поэтому заранее предопределить вызовы внутри приложения
    > не получится. Они переменны и в каждой DLL будут уникальны.

    Если разработчику приложения заранее известны имена функций в dll и их параметры, то ничто не мешает стандартному вызову этих функций в приложении. Если нет, то как их вообще можно разумно вызвать? Даже если приложению сказать что есть dll-имярек, в которой есть функция-имярек, у которой N параметров такого-то типа. Вызвать-то её теоретически можно, но вот какие значения параметров при этом передавать, если про смысл этих параметров приложение заранее не знает!
  • Германн © (10.12.10 02:15) [38]
    Забыл упомянуть что такая же неопределенность существует и для результата функции вызванной из библиотеки. С той лишь разницей, что "обычные" плагины основной результат, как правило, "обрабатывают сами". А во внешнее приложение только сообщают об ошибке, если таковая случится.

    P.S. Эта мода на плагины уже достала.
    Не на форуме, а от заказчиков.
  • Сергей М. © (10.12.10 16:19) [39]
    Удалено модератором
  • Сергей М. © (10.12.10 16:27) [40]
    Удалено модератором
  • Styx (13.12.10 19:00) [41]
    По-моему, автору вот это надо:
    http://ru.wikipedia.org/wiki/DLL
    program Example;
    {$APPTYPE CONSOLE}

    var result: Double;
        LibHandle: Hmodule;
        AddNumbers: function(a, b: Double): Double;
    begin
      LibHandle := LoadLibrary('Example.dll'); // загружаем DLL
      if LibHandle <> 0 then
        begin
          @AddNumbers := GetProcAddress(LibHandle, 'AddNumbers'); // запоминаем адрес
                                                                  // необходимой функции
          if @AddNumbers <> nil then
            begin
              result := AddNumbers(1, 2);       // используем функцию
              Writeln('The result was: ', result);
            end;
          FreeLibrary(LibHandle);               // выгружаем DLL
        end;
    end.

  • clickmaker © (13.12.10 19:14) [42]
    > Вот-вот. Как rundl работает?

    push
    push
    ...
    push
    call ?
  • Vidog © (17.12.10 01:19) [43]

    > По-моему, автору вот это надо:

    Как раз таки нет. Я же писал, что без предопределения функции. Вызов динамический.
  • Германн © (17.12.10 01:53) [44]

    > Как раз таки нет. Я же писал, что без предопределения функции.
    >  Вызов динамический.

    Вот Незнайка (Не прими на свой счёт. Имеется в виду персонаж известного произведения Н. Носова :) тоже хотел иметь волшебную палочку. Он её и получил после совершения трех хороших поступков. Но что было далее? Прочитай. Полезно будет.
  • Leonid Troyanovsky © (17.12.10 19:25) [45]

    > Германн ©   (17.12.10 01:53) [44]

    >  Но что было далее?

    Надругался над Дюймовочкой, ака Жаба? :)

    --
    Regards, LVT.
  • Styx (18.12.10 01:09) [46]

    > Как раз таки нет. Я же писал, что без предопределения функции.
    >  Вызов динамический.

    Так ведь

    Vidog ©   (30.11.10 20:34) [2]
    > А если я заведомо знаю ... кол-во параметров...

    Что тогда подразумевается под "знанием", если не предопределение типа функции?
  • Германн © (18.12.10 02:15) [47]

    > Leonid Troyanovsky ©   (17.12.10 19:25) [45]
    >
    >
    > > Германн ©   (17.12.10 01:53) [44]
    >
    > >  Но что было далее?
    >
    >

    Тебе тоже стоит прочитать. :)
    Ибо наломал Незнайка, а исправлять-то придётся волшебнику! :)
  • Vidog © (18.12.10 19:09) [48]

    > Что тогда подразумевается под "знанием", если не предопределение
    > типа функции?


    Просто физически известно, что функция называется Sum и у нее 2 параметра: A и B

    без определения функции Sum, нужно подключиться к библиотеке, найти адрес функции, послать ей массив из 2х элементов и получить результат.
  • Styx (18.12.10 19:37) [49]

    > послать ей массив

    Обязательно массив? Если нет, то не очень понятно, чем приведённый пример не устраивает.
    var AddNumbers: function(a, b: Double): Double; - это не определение функции, это определение переменной, имеющий тип функции с двумя параметрами типа Double. А далее, собственно, всё, как Вы и говорите - загружаем библиотеку, находим в ней адрес функции и вызываем. А как иначе вы расскажете компилятору, то, что Вам > физически известно? Если не нравится - пишите на ассемблере, но исполнимый код-то в результате всё равно получится такой же.
  • Сергей М. © (19.12.10 16:35) [50]

    > известно, что функция называется Sum и у нее 2 параметра:
    >  A и B
    >
    > без определения функции Sum, нужно подключиться к библиотеке,
    >  найти адрес функции, послать ей массив из 2х элементов
    > и получить результат


    Ожидаемый результат ты не получишь, с вероятностью ориентировочно фифти-фифти)
    Потому что знания имени точки входа, кол-ва параметров и даже их типов НЕдостаточно для успешной эксплуатации функции.
    Как минимум нужно достоверно знать еще и соглашение о вызове.
  • Petuh (01.09.11 23:10) [51]

    > clickmaker ©   (13.12.10 19:14) [42]
    > > Вот-вот. Как rundl работает?pushpush...pushcall ?

    Господин, Вы, кажется, забыли про стандарты вызова.. Даже это будет не так-то и просто..
 
Конференция "WinAPI" » Динамическая загрузка DLL
Есть новые Нет новых   [134431   +10][b:0.001][p:0.003]