1

dll をインポートする vba コードがあります。コードは次のとおりです。

Declare PtrSafe Function g77alscal Lib "g77alscal.dll" _
Alias "g77alscal_" _
(ByRef Nrows As Long, _
ByRef Ncols As Long, _
ByRef Xinput As Single, _
ByRef MDSout As Single, _
ByRef Metric As Single, _
ByRef Sout As Single, _
ByRef Niter As Long, _
ByRef Xdebug As Single, _
ByRef Idebug As Long) As Long

vbaでの呼び出しは

Dim Distance() As Single
Dim MDSout() As Single
Dim Metric(60) As Single
Dim Sout(2) As Single
Dim Niter As Long
Dim Xdebug(5000) As Single
Dim Idebug(30) As Long
Dim ierr As Long

N = CLng(Ncases)


ierr = g77alscal(N, N, Distance(1, 1), MDSout(1, 1), Metric(1), _
                 Sout(1), Niter, Xdebug(1), Idebug(1))

C#で私は使用しようとしました:

[DllImport("g77alscal.dll",EntryPoint="g77alscal_")]
static extern double g77alscal(ref long nRows, 
        ref long nCols,
        ref double xInput,
        ref double mdsOut,
        ref double metric,
        ref double sOut,
        ref long nIter,
        ref double xDebug,
        ref long iDebug
    );

そして、c# 関数の呼び出しは次のとおりです。

long n1 = Distance.Rows.Count;
long n2 = Distance.Columns.Count;
double n3 = double.Parse(Distance.Rows[0].ItemArray[0].ToString());
double n4 = 0;
double n5 = 0;
double n6 = 0;
double n7 = 0;
long n8 = 0;

double result = g77alscal(ref n1, ref n2, ref  n3,
    ref n4, ref n5, ref n6, ref nIter, ref n7, ref n8);

コードはコンパイラ エラーを渡しましたが、1 つの実行時エラー (FatalExecutionEngineError 例外) がありました。エラーは次のとおりです。

ランタイムで致命的なエラーが発生しました。エラーのアドレスは、スレッド 0x13a0 の 0x73c36e93 でした。エラー コードは 0xc0000005 です。このエラーは、CLR のバグ、またはユーザー コードの安全でない部分または検証不可能な部分のバグである可能性があります。このバグの一般的な原因には、COM 相互運用機能または PInvoke のユーザー マーシャリング エラーが含まれ、スタックが破損する可能性があります。

dll のドキュメントをまだ見つけていないので、fortran77 でコンパイルされたコードであること以外は dll について多くを語ることはできません。spssで使われているalscal関数の実装です。

c# の定義に何か問題がありますか? ヘルプやポインタは非常に役立ちます。

ありがとう。

更新: C# のコードを次のように変更しようとしました。

[DllImport("g77alscal.dll",EntryPoint="g77alscal_")]
    static extern int g77alscal(ref int nRows, 
        ref int nCols,
        ref float xInput,
        ref float mdsOut,
        ref float metric,
        ref float sOut,
        ref int nIter,
        ref float xDebug,
        ref int iDebug
    );

そして呼び出し:

int n1 = 21;
int n2 = 21;
float n3 = float.Parse(Distance.Rows[0].ItemArray[0].ToString());
float n4 = 0;
float n5 = 0;
float n6 = 0;
float n7 = 0;
int n8 = 0;

int result = g77alscal(ref n1, ref n2, ref  n3,
    ref n4, ref n5, ref n6, ref nIter, ref n7, ref n8);

さらに、別のパターンを見つけました。コードにブレークポイントを指定してアプリケーションを実行すると、上記のエラー例外がスローされますが、デバッグを行わないと例外がAccessViolationExceptionスローされます。

4

1 に答える 1

1

元の「vba バージョン」では、型Singleを使用していくつかのパラメーターを渡します。これは、4 バイトの浮動小数点数である必要があります。C# では同等である必要がありますfloat

コードで使用したのdoubleは、8 バイトの浮動小数点数です。これにより、関数がスタックをクリーンアップして返そうとするときに問題が発生しました。

整数型にも同じ問題があるようですLong。vba では 4 バイト、C# ではlong8 バイトです。int代わりに使用する必要があります。

とに変更doubleしてみてください。floatlongint

于 2013-02-23T07:11:54.683 に答える