BASICAcc でCDECLの32ビットDLLを使う方法

 投稿者:SHIRAISHI Kazuo  投稿日:2019年12月29日(日)18時27分20秒
  BASICAcc1.2 source\Winlib.pasの226行目
       result:=ProcAddr;
の直後に,
       // restore stack  (assume Cdecl)
       for i:=0 to High(a) do
         begin
           asm
             pop EAX
           end;
         end;
を追加すればCdeclの32ビットDLLが使えます。
(Lazarusを起動する必要はありません)
ただし,stdcallとは両立しません。

http://hp.vector.co.jp/authors/VA008683/

 

Re: BASICAcc でCDECLの32ビットDLLを使う方法

 投稿者:しばっち  投稿日:2020年 1月 1日(水)09時45分6秒
  > No.4756[元記事へ]

SHIRAISHI Kazuoさんへのお返事です。

> BASICAcc1.2 source\Winlib.pasの226行目
>        result:=ProcAddr;
> の直後に,

こちらでは226行目は
  i:integer;
となっています。

まず、確認ですが
BASICAcc1202

winlib.pasのファイルサイズ16,260 バイト
更新日時 2018年12月3日、15:13:54
となっています。

こちらでは
       result:=ProcAddr;

は265行目となります。
他に548行目にもあります。

下記は221行目からのコピペです

function Assign(const DLLName,FUNCName:string; a:array of const):cardinal;
var
  handle:THandle;
  ProcAddr:TLongIntFunction;
  params:PPointerArray;
  i:integer;
  p:pointer;
begin
   Handle:=LoadLibrary(PChar(ExtractFilePath(Application.ExeName)+DLLName));
  if Handle=0 then
     Handle:=LoadLibrary(PChar(DLLName));
  if (Handle=0) then
     SetExceptionWith(DLLName+' Not Found',DLL_Error);

  @ProcAddr:=GetProcAddress(Handle,PChar(FuncName));
  if @ProcAddr=nil then
                 SetExceptionWith(FuncName+' Not Found',DLL_Error);

  params:=AllocMem(sizeof(pointer)*Length(a));
  try
    for i:=0 to High(a) do
     with a[i] do
      begin
       case VTYPE of
        VTINTEGER:   longint(params^[i]):=VInteger;
        VTInt64:     Cardinal(params^[i]):=VINT64^;
        VTExtended:  longint(params^[i]):=RoundToLongint(VExtended^);
        vtAnsistring:params^[i]:=PChar(VAnsistring);
       else
        setexceptionWith(IntToStr(i)+'th Parameter imcompatible',Dll_Error);
       end;
      end;


     try
       for i:=high(a) downto 0 do
         begin
           p:=@params^[i];
           asm
             mov eax, p
             push dword ptr [eax]
           end;
         end;

       result:=ProcAddr;

もう一度ご確認ください。
 

Re: BASICAcc でCDECLの32ビットDLLを使う方法

 投稿者:SHIRAISHI Kazuo  投稿日:2020年 1月 1日(水)13時55分9秒
  > No.4758[元記事へ]

しばっちさんへのお返事です。

32ビット版BASICAccだと265行目の直後でした。
64ビット版公開のために不要なプロシージャを削除して修正した後であることを忘れていました。
なお,function Assign は通常のASSIGN文に対応しますが,
AssignFPU(323行めの後)
TSyncAssign.exec(201行目の後)
も同様の修正が可能です。
ASSIGNFPUは,ASSIGN ○,○, FPU
TSyncAssign.exec は ASSIGN ○,○,GUI
に対応します。


> SHIRAISHI Kazuoさんへのお返事です。
>
> > BASICAcc1.2 source\Winlib.pasの226行目
> >        result:=ProcAddr;
> > の直後に,
>
> こちらでは226行目は
>   i:integer;
> となっています。
>
> まず、確認ですが
> BASICAcc1202
>
> winlib.pasのファイルサイズ16,260 バイト
> 更新日時 2018年12月3日、15:13:54
> となっています。
>
> こちらでは
>        result:=ProcAddr;
>
> は265行目となります。
> 他に548行目にもあります。
>
> 下記は221行目からのコピペです
>
> function Assign(const DLLName,FUNCName:string; a:array of const):cardinal;
> var
>   handle:THandle;
>   ProcAddr:TLongIntFunction;
>   params:PPointerArray;
>   i:integer;
>   p:pointer;
> begin
>    Handle:=LoadLibrary(PChar(ExtractFilePath(Application.ExeName)+DLLName));
>   if Handle=0 then
>      Handle:=LoadLibrary(PChar(DLLName));
>   if (Handle=0) then
>      SetExceptionWith(DLLName+' Not Found',DLL_Error);
>
>   @ProcAddr:=GetProcAddress(Handle,PChar(FuncName));
>   if @ProcAddr=nil then
>                  SetExceptionWith(FuncName+' Not Found',DLL_Error);
>
>   params:=AllocMem(sizeof(pointer)*Length(a));
>   try
>     for i:=0 to High(a) do
>      with a[i] do
>       begin
>        case VTYPE of
>         VTINTEGER:   longint(params^[i]):=VInteger;
>         VTInt64:     Cardinal(params^[i]):=VINT64^;
>         VTExtended:  longint(params^[i]):=RoundToLongint(VExtended^);
>         vtAnsistring:params^[i]:=PChar(VAnsistring);
>        else
>         setexceptionWith(IntToStr(i)+'th Parameter imcompatible',Dll_Error);
>        end;
>       end;
>
>
>      try
>        for i:=high(a) downto 0 do
>          begin
>            p:=@params^[i];
>            asm
>              mov eax, p
>              push dword ptr [eax]
>            end;
>          end;
>
>        result:=ProcAddr;
>
> もう一度ご確認ください。
>
 

戻る