【问题标题】:Converting vba importdll code to c#将 vba importdll 代码转换为 c#
【发布时间】:2013-02-08 21:19:16
【问题描述】:

我有一个导入 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-interop 或 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

【问题讨论】:

    标签: c# vba marshalling dllimport fatal-error


    【解决方案1】:

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

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

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

    尝试将double 更改为float 并将long 更改为int

    【讨论】:

    • 经过更多测试后,确切的错误再次出现。如果不是,则将出现访问冲突异常。还有什么想法吗?
    • @SyakurRahman 你确定这是 exact 例外吗?也许不是同一段代码?
    • 我相信 vba 中的 long 也是 4 字节 int 和 c# 中的 8 字节 int
    • 是的,它是同一段代码。我尝试逐个语句跟踪,以确保确切的行触发了异常。写的错误和我上面贴的一模一样,只是地址和错误码不同。
    • 我的意思是编辑您的问题以显示在 c# 中定义和调用 dll 以反映您所做的更改的更新代码。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-07-22
    • 1970-01-01
    • 2015-07-10
    • 1970-01-01
    • 2012-04-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多