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);

该代码传递了编译器错误,但它有一个运行时错误(FatalExecutionEngineError 异常)。错误是:

运行时遇到致命错误。错误地址位于线程 0x13a0 上的 0x73c36e93。错误代码为 0xc0000005。此错误可能是 CLR 中的错​​误或用户代码的不安全或不可验证部分中的错误。此错误的常见来源包括 COM 互操作或 PInvoke 的用户封送错误,这可能会损坏堆栈。

我还没有找到 dll 的文档,所以我不能对 dll 说太多,除了它是一个 fortran77 编译代码。它是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就会抛出 an 。

4

1 回答 1

1

你原来的“vba 版本”使用类型Single来传递一些参数,应该是一个 4 字节的浮点数。它在 C# 中的等价物应该是float.

您在代码中使用的double是 8 字节浮点数。当函数尝试清理堆栈并返回时,这会导致问题。

整数类型似乎也有同样的问题,其中Longvba 是 4 字节,而 C#long是 8 字节。你应该int改用。

尝试更改doublefloat和。longint

于 2013-02-23T07:11:54.683 回答