调用Pascal DLL后Excel崩溃

调用Pascal DLL后Excel崩溃,excel,vba,dll,pascal,Excel,Vba,Dll,Pascal,我用免费的Pascal编写了一个DLL,并想用Excel调用它。如果有人能帮我,我将不胜感激 用于测试的免费Pascal DLL是 procedure chess(var number : single);stdcall; begin WriteLn(output,'Wir testen die Zahl: ', number); end; exports chess; begin end. 在Excel中,我有以下VBA代码 Private Declare PtrS

我用免费的Pascal编写了一个DLL,并想用Excel调用它。如果有人能帮我,我将不胜感激

用于测试的免费Pascal DLL是

procedure chess(var number : single);stdcall;
begin
    WriteLn(output,'Wir testen die Zahl: ', number);
end;

exports
       chess;
begin
end. 
在Excel中,我有以下VBA代码

Private Declare PtrSafe Sub chess Lib "D:\FS\LTMProjekt\TestWB\CLModul_lib.dll" (ByVal Number As Single)
当我用
callchess(TSim)
Excel在VBA中调用DLL时,会崩溃并自动关闭。 在过去的几天里,我不知道为什么,现在真的很沮丧。 希望有人能帮我

提前谢谢

编辑:

DLL的Pascal代码:

library CLM_WEAdynModell;
{$mode objfpc}{$H+}

uses
    CLM_GlobalVariables, CLM_LoadCalc, CLM_Initialization;
   
type
    IOA = array[1..150] of single; 

procedure callTModel(var IOArray : IOA); stdcall; 
begin
     getInputValues(IOArray);
     defineModel;
     calcSecForces;
     writeOutputValues(IOArray);
     writeLogFile(IOArray);
end; 

exports
       callTModel;
begin
end.
VBA代码:

Option Explicit 
Private Declare PtrSafe Sub callTModel Lib "D:\FS\LTMProjekt\TestWB\CLM_WEAdynModell.dll" (ByRef IOArray() As Single)

Private Sub CB_RUN_Click()

Dim ValID, TStep, INLimit, aIndex, bIndex, ActSensor, VisNmax, OUTLimit, i As Integer
Dim TSim, TMax As Single
Dim IOArray(149) As Single

With ActiveSheet

TStep = 0
ValID = 0
INLimit = 9   
VisNmax = 20  

ActSensor = .Range("NoSensor").Value + 1
OUTLimit = .Range("OUTLimit")
TSim = 0
TMax = .Range("TMax")

    ThisWorkbook.Worksheets("IstRes").Range("A4:IV8000").ClearContents
 
Application.ScreenUpdating = False

 Do While TSim < TMax
    TSim = .Range("TSim")
    
    aIndex = (4 + TStep) 'Zeilenindex für Source Array
    For i = 1 To INLimit
     bIndex = (1 + i)     ' Spaltenindex für Source Array
      
     If (i < 10) Then IOArray(24 + i) = ThisWorkbook.Worksheets("SourceData").Cells(aIndex, bIndex).Value
     bIndex = bIndex + INLimit
     If (i < 10) Then IOArray(39 + i) = ThisWorkbook.Worksheets("SourceData").Cells(aIndex, bIndex).Value
     bIndex = bIndex + INLimit
     If (i < 4) Then IOArray(7 + i) = ThisWorkbook.Worksheets("SourceData").Cells(aIndex, bIndex).Value
     bIndex = bIndex + 3
     If (i < 4) Then IOArray(19 + i) = ThisWorkbook.Worksheets("SourceData").Cells(aIndex, bIndex).Value
          
    Next i
    
    IOArray(101) = OUTLimit
    
    Call callTModel(IOArray)
    
    
    aIndex = (4 + TStep) 'Zeilenindex für Target Array
    ThisWorkbook.Worksheets("IstRes").Cells(aIndex, 1).Value = ThisWorkbook.Worksheets("SourceData").Cells(aIndex, 1).Value
    For i = 1 To OUTLimit
     bIndex = (1 + i)     ' Spaltenindex für Source Array
     ThisWorkbook.Worksheets("IstRes").Cells(aIndex, bIndex).Value = IOArray(101 + i)
    Next i
 
    Application.ScreenUpdating = True
     If TStep < VisNmax Then
      .Cells(9 + TStep, 3).Value = ThisWorkbook.Worksheets("SollRes").Cells(aIndex, ActSensor).Value
      .Cells(9 + TStep, 4).Value = ThisWorkbook.Worksheets("IstRes").Cells(aIndex, ActSensor).Value
     Else
      For i = 1 To (VisNmax - 1)
       .Cells(8 + i, 3).Value = .Cells(9 + i, 3).Value
       .Cells(8 + i, 4).Value = .Cells(9 + i, 4).Value
      Next i
      .Cells(8 + VisNmax, 3).Value = ThisWorkbook.Worksheets("SollRes").Cells(aIndex, ActSensor).Value
      .Cells(8 + VisNmax, 4).Value = ThisWorkbook.Worksheets("IstRes").Cells(aIndex, ActSensor).Value
     End If
    
    TStep = TStep + 1
    .Range("TStep") = TStep
   
    Call ScrUpdateEnableNoFlicker
    
    Application.ScreenUpdating = False
    
 Loop ' Ende DoWhile TSim <= TMax


End With ' ActiveSheet
'Application.ScreenUpdating = True


End Sub
选项显式
私有声明PtrSafe子调用模型库“D:\FS\LTMProjekt\TestWB\CLM_weadynodell.dll”(ByRef IOArray()作为单个)
专用子CB_运行_单击()
Dim ValID、TStep、INLimit、aIndex、bIndex、ActSensor、VisNmax、OUTLimit、i为整数
昏暗的尖峰,TMax为单曲
Dim IO阵列(149)作为单个
使用ActiveSheet
t步骤=0
有效=0
INLimit=9
VisNmax=20
ActSensor=.范围(“鼻传感器”).值+1
OUTLimit=.Range(“OUTLimit”)
TSim=0
TMax=.Range(“TMax”)
此工作簿。工作表(“IstRes”)。范围(“A4:IV8000”)。ClearContent
Application.ScreenUpdating=False
当TSimLoop’Ende DoWhile TSim这里是一个在VBA和Delphi之间传递数组参数的示例。
Delphi函数计算数组元素的和。为了使用任意长度的数组,参数被声明为带on的指针(第一个函数)或(第二个函数)

VBA调用在这两种情况下都有两个参数
SumOfArrayElements1
需要指向数组第一个元素和元素数的指针。
SumOfArrayElements2
的单个打开数组参数在VBA中也需要两个参数:指向第一个元素的同一指针和最后一个索引。在Delphi中,对于一个开放数组,第一个索引总是0,最后一个索引是数组长度减1

Delphi:

library calc;

{$POINTERMATH ON}

type preal = ^real;

function SumOfArrayElements1(a: preal; n: integer): real;
var i: integer;
begin
    Result := 0;
    for i := 0 to n - 1 do
        Result := Result + a[i]
end;

function SumOfArrayElements2(a: array of real): real;
var i: integer;
begin
    Result := 0;
    for i := Low(a) to High(a) do
        Result := Result + a[i]
end;

exports
    SumOfArrayElements1, SumOfArrayElements2;
end.
VBA

Option Explicit
Option Base 1
Declare PtrSafe Function SumOfArrayElements1 Lib "calc" (ByRef X As Double, ByVal N As Long) As Double
Declare PtrSafe Function SumOfArrayElements2 Lib "calc" (ByRef X As Double, ByVal N As Long) As Double
Sub Test()
    Dim A() As Double, I As Long, N As Long
    N = 100
    ReDim A(N)
    ChDrive ThisWorkbook.Path
    ChDir ThisWorkbook.Path
    For I = 1 To N
        A(I) = I
    Next I
    Debug.Print SumOfArrayElements1(A(1), N)
    Debug.Print SumOfArrayElements2(A(1), N - 1)
End Sub

注意:VBA中的ChDrive/ChDir对于VBA查找DLL是必需的,因为它存储在与Excel文件相同的目录中。

Pascal中的var是VBA中的ByRef。所以它在一个错误的指针值上死亡。既然ByVal在这里有意义,只需省略var。谢谢。我在Pascal代码中省略了var,但Excel仍然崩溃。您需要添加在Excel中使用的实际代码来调用Chess。如何在dll代码中定义outputWriteLn(output,'Wir testen die Zahl:',number)?如果我用一个简单的
嘟嘟声替换那一行只是为了得到一些指示,它工作正常。它与
beep一起工作对我来说也是<代码>输出
定义为
var输出:文本文本文档是否可能导致问题?