создание dll под фпц

Вопросы программирования на Free Pascal, использования компилятора и утилит.

Модератор: Модераторы

создание dll под фпц

Сообщение Attid » 20.08.2007 18:11:12

а ткнитика меня в особености создания длл под фпц.

хотел плагин под IBexpert написать, стянул исходник тестового плагина под дельфю, создал проэкт в лазаре скопипастил, скомпилил,
и тишина =( не видит его эксперт пример функции в длл

Код: Выделить всё
procedure get_plugin_info_ex(Intf: TIBEInterfaceEx; PluginInfo: pointer); stdcall;
begin
  with PIBEPluginInfoEx(PluginInfo)^ do
  begin
    PluginName := 'Just a test plugin';
    Description := 'No description';
    PlaceMenu := '2;11';
    MenuStructure := PChar('CFormat Statement (Example)|B|Uplugin_update_action_ex' + #13#10 +
                           '    CFormat Statement|Eformat_select');
  end;
end;

exports
  get_plugin_info_ex,

Аватара пользователя
Attid
долгожитель
 
Сообщения: 2586
Зарегистрирован: 27.10.2006 17:29:15
Откуда: 44°32′23.63″N 41°2′25.2″E

Сообщение Attid » 12.11.2007 22:17:33

код на дельфи который вызывает эксперт при загрузке
Код: Выделить всё
procedure TIBEPluginsList.LoadPlugin(const FileName: string);

var

  PluginInfoEx : PIBEPluginInfoEx;

  GetInfoEx : TGetPluginInfoProcEx;

  Lib: THandle;

  Plugin : TIBEPlugin;

begin

  Lib := Windows.LoadLibrary(PChar(FileName));

  if Lib <= HINSTANCE_ERROR then

    Exit;

  try

    GetInfoEx := GetProcAddress(Lib, PChar('get_plugin_info_ex'));

    if (@GetInfoEx = nil) then

      Exit;

    New(PluginInfoEx);

    try

      GetInfoEx(IBEIEx, PluginInfoEx);



      Plugin := TIBEPlugin.Create;

      Plugin.FileName := FileName;

      Plugin.PluginName := PluginInfoEx.PluginName;

      Plugin.Description := PluginInfoEx.Description;

      Plugin.PlaceMenu := PluginInfoEx.PlaceMenu;

      Plugin.CreatePluginMenu(PluginInfoEx.MenuStructure);



      Self.Add(Plugin);

    finally

      Dispose(PluginInfoEx);

    end;

  finally

    FreeLibrary(Lib);

  end;

end;


Аватара пользователя
Attid
долгожитель
 
Сообщения: 2586
Зарегистрирован: 27.10.2006 17:29:15
Откуда: 44°32′23.63″N 41°2′25.2″E

Сообщение Юра » 12.11.2007 22:20:40

PIBEPluginInfoEx глянь. Если там используются длинные строки в качестве полей, то плохо...
Юра
постоялец
 
Сообщения: 163
Зарегистрирован: 25.05.2005 10:20:09
Откуда: Украина, Киев

Сообщение Attid » 12.11.2007 23:05:32

Код: Выделить всё
  PIBEPluginInfoEx = ^TIBEPluginInfoEx;

  TIBEPluginInfoEx = record

    PluginName  : PChar;

    Description : PChar;

    MenuStructure : PChar;

    PlaceMenu : PChar;

  end;



IBEIntfEx.pas
Аватара пользователя
Attid
долгожитель
 
Сообщения: 2586
Зарегистрирован: 27.10.2006 17:29:15
Откуда: 44°32′23.63″N 41°2′25.2″E

Сообщение Юра » 13.11.2007 01:00:02

Проблема вероятно здесь:

MenuStructure := PChar('CFormat Statement (Example)|B|Uplugin_update_action_ex' + #13#10 +
' CFormat Statement|Eformat_select');

Здесь создается временная строка, которая при выходе из функции освобождается, и указатель на освобожденную память возвращается вызывающей программе.
Присвой строку глобальной переменной, а уже потом возвращай на нее указатель.
Либо для теста верни просто строковую константу.
Юра
постоялец
 
Сообщения: 163
Зарегистрирован: 25.05.2005 10:20:09
Откуда: Украина, Киев

Сообщение Attid » 13.11.2007 10:47:47

Код: Выделить всё
const mstr='CFormat Statement|B|'#13#10'   CFormat Statement|Eformat_selectd';
var Pcharmstr : PChar;

попробывал варианты
Код: Выделить всё
//    MenuStructure := mstr;
//    MenuStructure := PChar(mstr);
    Pcharmstr:=PChar(mstr);
    MenuStructure := Pcharmstr;


безполезно =( у меня вообще подозрения что PChar в 2,2,* сломали =) пойду попробую 2,0,4 поставить на вм
Последний раз редактировалось Attid 13.11.2007 21:25:41, всего редактировалось 1 раз.
Аватара пользователя
Attid
долгожитель
 
Сообщения: 2586
Зарегистрирован: 27.10.2006 17:29:15
Откуда: 44°32′23.63″N 41°2′25.2″E

Сообщение halyavin » 13.11.2007 11:57:16

А функцию plugin_update_action_ex вы экспортируете?
halyavin
новенький
 
Сообщения: 25
Зарегистрирован: 23.10.2007 16:35:55

Сообщение Attid » 13.11.2007 12:13:47

нет, но на дельфи я его тоже не экспортирую и тоже все работает.

как проверю на 2,0,4 попробую воспроизвести на минимальном примере.
Последний раз редактировалось Attid 13.11.2007 21:25:52, всего редактировалось 1 раз.
Аватара пользователя
Attid
долгожитель
 
Сообщения: 2586
Зарегистрирован: 27.10.2006 17:29:15
Откуда: 44°32′23.63″N 41°2′25.2″E

Сообщение halyavin » 13.11.2007 12:48:50

Я понял почему не работает dll'ка у меня - это ошибка компилятора (я юзаю довольно старый 2.0.4).
Код: Выделить всё
.globl   P$TESTEX_GET_PLUGIN_INFO_EX$TIBEINTERFACEEX$POINTER
P$TESTEX_GET_PLUGIN_INFO_EX$TIBEINTERFACEEX$POINTER:
# Temps allocated between ebp-8024 and ebp+0
   pushl   %ebp
   movl   %esp,%ebp
   subl   $8020,%esp
   movl   %eax,3928(%esp)
   pushl   %eax
   movl   %ebx,-8024(%ebp)
   movl   %esi,-8020(%ebp)
   movl   %edi,-8016(%ebp)
# Var Intf located at ebp+8
# Var PluginInfo located at ebp+12
# здесь копируется параметр Intf.
   movl   8(%ebp),%esi
   leal   -8008(%ebp),%edi
   cld
   movl   $2002,%ecx
   rep
   movsl

вместо movl 8(%ebp),%esi должно стоять leal 8(%ebp),%esi. В результате этой ошибки в esi оказывается ноль (первое поле структуры TIBEInterfaceEx), а не указатель на структуру в стеке и происходит исключение при копировании параметра Intf. Так что нужно найти версию компилятора, в которой на этом месте будет стоять leal. Кроме этого, могут возникнуть проблемы с разным выравниванием структур в fpc/delphi. И не следует забывать о директиве {$MODE} - без нее integer двухбайтный.
Если у вас в дизасме стоит leal, то выложите куда-нибудь скомпиленную dll'ку вместе с ассемблерным листингом (семейство опций -a).
PS Это ошибка прошла не замеченной скорее всего потому, что никто 8Kb структуры копированием не передает - но поправлять IBExpert похоже уже поздно.
halyavin
новенький
 
Сообщения: 25
Зарегистрирован: 23.10.2007 16:35:55

Сообщение Attid » 13.11.2007 21:28:26

halyavin
в мантис отпишешь ?

архив тута
Аватара пользователя
Attid
долгожитель
 
Сообщения: 2586
Зарегистрирован: 27.10.2006 17:29:15
Откуда: 44°32′23.63″N 41°2′25.2″E

Сообщение halyavin » 14.11.2007 15:44:36

Хм... все оказывается немного хитрее, чем я думал. Free Pascal по-другому передает большие параметры - он запихивает в стек указатель на структуру, а в процедуре его копирует. Delphi же записывает в стек саму структуру и в процедуре параметр тоже копирует. Поэтому в программах, написанных целиком на Free Pascal, или целиком на Delphi все нормально. А вот на границе dll получаются глюки (как при вызове Free Pascal из Delphi, так и наоборот). Кто соотвествует стандартам в данном случае - не понятно.
halyavin
новенький
 
Сообщения: 25
Зарегистрирован: 23.10.2007 16:35:55

Сообщение Sergei I. Gorelkin » 14.11.2007 16:15:54

Погодите, погодите... Что-то я не припомню, чтобы Дельфи структуры по значению передавал. А FPC теоретически это может делать - он поступает в соответствии с ABI конкретной операционки, некоторые из которых (один из примеров - powerpc/darwin) предписывают запихивать структуры в стек целиком (зачем - остается совершенно непонятным).

Может быть, во избежание копирования, надо объявлять параметр Intf как const или var?
Аватара пользователя
Sergei I. Gorelkin
энтузиаст
 
Сообщения: 1406
Зарегистрирован: 24.07.2005 14:40:41
Откуда: Зеленоград

Сообщение halyavin » 14.11.2007 16:23:50

Тут как раз лишние копирование у дельфи, а не у fpc. Поэтому ни var, ни const не вылечат (точнее если поставить var и в вызывающем коде и в вызываемом, то будет все ok, но вызывающий код на дельфи мы править-то не можем). Дельфи прекрасно передает структуры по значению, иначе бы код исходного дельфового плагина не компилился.
halyavin
новенький
 
Сообщения: 25
Зарегистрирован: 23.10.2007 16:35:55

Сообщение Юра » 14.11.2007 17:19:16

Мы говорим про stdcall. И если для него дельфи пихает всю структуру в стек, то FPC должен делать также. Иначе не будет совместимости, как в данном случае...
Юра
постоялец
 
Сообщения: 163
Зарегистрирован: 25.05.2005 10:20:09
Откуда: Украина, Киев

Сообщение Sergei I. Gorelkin » 14.11.2007 17:44:57

Забавная получается хрень, однако...
Действительно, пока нет stdcall - передает указатель и копирует в вызываемой процедуре. Добавляем stdcall - начинает пихать все в стек на вызывающей стороне. При этом в WinAPI ведь нет ни одной ф-ции, для которой это могло бы быть нужно...
Аватара пользователя
Sergei I. Gorelkin
энтузиаст
 
Сообщения: 1406
Зарегистрирован: 24.07.2005 14:40:41
Откуда: Зеленоград

След.

Вернуться в Free Pascal Compiler

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 11

Рейтинг@Mail.ru