F#から外部DLL関数にアクセスしようとしています。これは本当に汗をかきます。
Cヘッダーは次のとおりです。
ext_def(int32) swe_calc_ut(double tjd_ut, int32 ipl, int32 iflag,
double *xx, char *serr);
それに応じてF#にインポートしました:
extern int32 ext_swe_calc_ut(double tjd_ut, int32 ipl, int32 iflag, double *xx, StringBuilder serr);
問題は配列部分です。F#PowerpackからPinnedArrayを試しましたが、それでも呼び出しは失敗します。呼び出しが失敗したために確認できませんが、char配列はおそらく問題ありません。
これまでのところ:
open System
open System.Runtime.InteropServices
open System.Text
open Microsoft.FSharp.NativeInterop
#r "FSharp.PowerPack.dll"
#nowarn "51"
module Sweph =
[<DllImport(@"swedll32.dll", CharSet = CharSet.Ansi, EntryPoint = "swe_calc_ut")>]
extern int32 ext_swe_calc_ut(double tjd_ut, int32 ipl, int32 iflag, double *xx, StringBuilder serr);
/// <param name="jdnr">Julian day</param>
/// <returns>Array with 6 doubles: 0:longitude, 1:latitude, 2:distance,3:speel in longitude,
/// 4: speed in latitude, 5: speed in distance </returns>
let ar: double array = Array.zeroCreate 6
let argx = PinnedArray.of_array ar
printfn " ar: %A" ar
// This fails with a "FileLoadException"
printfn "ar: %A" argx
// Details of FileLoadException:
(*
"FSharp.Core、Version = 2.0.0.0、Culture = neutral、PublicKeyToken = b03f5f7f11d50a3a"アセンブリが一致しません(Ausnahme von HRESULT:0x80131040)*)
// However, if I leave the printfn for argx out, code continues and does not display this error again.
let sb = new StringBuilder(50) // Vgl. Expert F#, S. 515
Console.ReadKey(true)
// Application crashes here:
let ret_calc = Sweph.ext_swe_calc_ut(4700.0,1,1,argx.Ptr,sb)
この時点でプログラムがクラッシュします(コンソールウィンドウが消え、デバッグ中は最初の行にジャンプして戻ります。
「letargx=PinnedArray.of_array ar」で「let」の代わりに「use」を使用できることは知っていますが、上部にモジュール宣言があるため、コンパイラーはそれを許可しません。
C#には次のような実装があります。
public static double[] getPlanet(int ipl, double jdnr) {
// String ephePath = "Q:\\sweph\\";
// Sweph.setEphePath(ephePath);
double[] xx2 = new double[8];
double[] xx = new double[6];
String serr = "";
int iflag = Constants.SEFLG_SPEED;
long iflgret = ext_swe_calc_ut(jdnr, ipl, iflag, xx, serr);
for (int i = 0; i < 6; i++) {
xx2[i] = xx[i];
}
iflag = Constants.SEFLG_SWIEPH | Constants.SEFLG_SPEED | Constants.SEFLG_EQUATORIAL;
iflgret = ext_swe_calc_ut(jdnr, ipl, iflag, xx, serr);
xx2[6] = xx[0];
xx2[7] = xx[1];
return xx2;
}
おそらく、問題全体がFileLoad例外に戻っている可能性があります(dll呼び出しに表示されていなくても)-おそらくFSharp Powerpackが原因ですか?
本当にありがとうございました。