HSPポータル
サイトマップ お問い合わせ


HSPTV!掲示板


未解決 解決 停止 削除要請

2009
0110
Hiroaki SoftwareDLLからの呼び出し3解決


Hiroaki Software

リンク

2009/1/10(Sat) 18:34:21|NO.22638

Delphi 6でDLL作ったのですが
それをHSPで呼び出すとおかしくなるのです

この件別のところで質問してもよいのですが、
HSPでの呼び出し時の問題なのでここで質問させていただきます。

まず
Delphiのプロジェクトに入力した内容を書きます

-------------Himath.dpr-----------------------
library HiMath;


uses
SysUtils,
Classes;
{$R *.res}


function factorial (n:Integer):integer;stdcall;
//nは整数、nが-1以下の場合-1が返る
var
buf,buf1,buf2 :integer;

begin
if n=0 then factorial:=1 else
begin
if n<0 then factorial:=-1 else
begin
buf:=n;
buf2:=1;
repeat
buf1:=buf-1;
if buf1=0 then buf1:=1;
buf2:=buf2*buf*buf1;
buf:=buf-2 ;
factorial:=buf2;
//txt:=floattotext(buf2);
until buf<=0;

end;
end;

end;

exports
factorial;
begin
end.
-----------------------------------------------
この命令 階乗を計算するものです

そこでhsp上で

#uselib "HiMath.dll" #cfunc factorial "factorial" int
と呼び出して
print factorial(13)

としたら間違った値が出るのです どうにかなりませんか? ------------------------------------------------------------------------------ そこで同機能のものをHSPでモジュール化してみたら以下になります
#module
#defcfunc factorial int n //階乗
if n==0{
nb=1
}else:if n<0{
	nb=-1
}else{
   buf=n
     buf2=1.0
 do
        buf1=buf-1
            if buf1=0:buf1=1
        buf2=buf2*buf*buf1
          buf=buf-2 
          nb=buf2
 until(buf<=0)
}

return nb
#global


print factorial(13)
としたら正しい答えが出ます


とにかくDLLから呼び出したとき正しい答えにしたいのです



この記事に返信する


check

リンク

2009/1/10(Sat) 19:23:36|NO.22641

俺はDelphiについてはあまり詳しくはないが、
定義したfactorial関数はDelphi上で実行しても正しい値にならないのか?



New Monkey

リンク

2009/1/10(Sat) 20:38:59|NO.22656

計算結果がIntegerの範囲を超えるのでDoubleで返さないとダメです。
HSPでDouble型の戻り値を受け取るにはちょっと工夫が要ります。

<方法1>
HSP側の実数型の変数のポインタを渡し、DLL側でそこに結果を代入する方法

DLL側

library Project1; uses Windows; {$R *.res} procedure factorial(n: Integer; pret: PDouble); stdcall; var i: Integer; r: Double; begin r := 1; for i := 1 to n do begin r := r * i; end; MoveMemory(pret, @r, SizeOf(Double)); end; exports factorial; end.
HSP側

#uselib "Project1.dll" #func factorial "factorial" sptr, sptr ret = 0.0 factorial 13, varptr(ret) mes ret

------------------------------------------------------------------------------

<方法2>
裏技的になりますが、Double型の戻り値を取得するのにYOYOさんの方法を使わせてもらった方法です

DLL側

library Project1; {$R *.res} function factorial(n: Integer): Double; stdcall; var i: Integer; begin Result := 1; for i := 1 to n do begin Result := Result * i; end; end; exports factorial; end.
HSP側

#uselib "Project1.dll" #func factorial "factorial" sptr #module #uselib "kernel32.dll" #func VirtualProtect "VirtualProtect" int, int, int, int #deffunc getdouble if code == 0 { code=$0424448b,$04c218dd,$00000000 VirtualProtect varptr(code), length(code)*4, $40, varptr(res) fret=0.0 } prm = varptr(fret) res = callfunc(prm, varptr(code), 1) return fret #global factorial 13 getdouble mes refdval
--------------------

以下YOYOさんの書き込み


YOYO 2007/7/27(Fri) 01:28:25|NO.9784 整数と小数では返り値を渡す仕組みが異なるのでプラグインかマシン語で取り出す仕組みが必要です。 強引ですが、関数の返した小数を取り出すモジュールを作ってみました。 関数が返す少数はdoubleとfloatどちらでも大丈夫です。 #module #uselib "kernel32.dll" #func VirtualProtect "VirtualProtect" int, int, int, int #deffunc getdouble if code == 0 { code=$0424448b,$04c218dd,$00000000 VirtualProtect varptr(code), length(code)*4, $40, varptr(res) fret=0.0 } prm = varptr(fret) res = callfunc(prm, varptr(code), 1) return fret #global BASS_ChannelBytes2Seconds handle,pos getdouble //getdoubleは小数を返す命令の直後に呼び出してください。 mes refdval



Hiroaki Software

リンク

2009/1/11(Sun) 14:43:39|NO.22686

2人とも回答ありがとうございました



ONION software Copyright 1997-2021(c) All rights reserved.