C# &引用;试图读取或写入受保护的内存。这通常表示其他内存已损坏。”;Delphi7动态链接库#

C# &引用;试图读取或写入受保护的内存。这通常表示其他内存已损坏。”;Delphi7动态链接库#,c#,delphi,dll,C#,Delphi,Dll,从C#调用Delphi 7 DLL文件时遇到问题。我是C#的新手,对德尔菲了解不多,也不需要真正了解那么多。我只需要尽快解决这个问题 我试图从C#调用dll,但我得到了一个错误:“试图读取或写入受保护的内存。这通常表示其他内存已损坏。” 我不知道为什么会这样。正如您将在我的Delphi代码中看到的,我并没有试图返回任何值。我只需要在COM端口上发送一些命令。如果有人能帮我离开这里,请:( Delphi DLL代码: library Project2; uses SysUtils, C

从C#调用Delphi 7 DLL文件时遇到问题。我是C#的新手,对德尔菲了解不多,也不需要真正了解那么多。我只需要尽快解决这个问题

我试图从C#调用dll,但我得到了一个错误:“试图读取或写入受保护的内存。这通常表示其他内存已损坏。”

我不知道为什么会这样。正如您将在我的Delphi代码中看到的,我并没有试图返回任何值。我只需要在COM端口上发送一些命令。如果有人能帮我离开这里,请:(

Delphi DLL代码:

library Project2;


uses
  SysUtils,
  ComPort,
  Classes;

var com1:TComport ;

{$R *.res}
procedure moveforward; export;
begin
  com1.WriteAnsiString('#20 P1528 CR'+sLineBreak);
  com1.WriteAnsiString('#7 P1465 CR'+sLineBreak);
end;

procedure movebackward; export;
begin
  comport1.WriteAnsiString('#7 P1528 CR'+sLineBreak);
  comport1.WriteAnsiString('#20 P1465 CR'+sLineBreak);
end;

procedure stopmove;export;
begin
  comport1.WriteAnsiString('#20 P1500 CR'+sLineBreak);
  comport1.WriteAnsiString('#7 P1500 CR'+sLineBreak);
end;

procedure catch; export;
begin
  comport1.WriteAnsiString('#2 P2120 T2000 CR'+sLineBreak); //arm
  comport1.WriteAnsiString('#30 P2260 T500 CR'+sLineBreak); //gripper
end;

procedure initialize; export;
begin
  comport1.WriteAnsiString('#2 P2184 T1000 CR'+sLineBreak); //arm
  comport1.WriteAnsiString('#30 P1980 T2000 CR'+sLineBreak); //gripper
end;

exports  
  moveforward, movebackward, stopmove, catch, initialize;

begin
end.
C#代码

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace WindowsFormsApplication3
{
    public partial class Form1 : Form
    {
        [System.Runtime.InteropServices.DllImport("Project2.dll")]
        public static extern void moveforward();
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            moveforward();
        }
    }
}
我们真诚地感谢您的帮助

编辑:

请注意,经过进一步思考,我非常确定这不是正确的答案。使用不匹配的调用约定仍然是一个坏主意(因此我最初的直觉认为这是问题),但在这种情况下,这可能不是GPF的原因

原件:

99%的情况下,此错误表示您的调用约定错误。我已经有一段时间没有用Delphi编写了,但我认为这将解决您的问题:

procedure moveforward; export; stdcall;
当您只使用一个编译器时,通常不会出现问题,因为所有编译器都使用同一个编译器。当您混合使用语言时,甚至当您混合使用不同供应商的编译器时,这可能是一个问题。调用约定决定了调用的哪一端必须清理参数;如果双方都尝试这样做,则可能会导致GPF。


默认情况下,该属性使用调用约定
CallingConvention.StdCall
,但您可以在属性本身中重写该约定。不幸的是,Delphi的默认调用约定是不受支持的类型(或者称为fastcall或register),因此,您唯一的选择是将Delphi端更改为使用stdcall。

Delphi代码从不为全局
com1
变量赋值。您需要使其引用一个
t导入
实例。导出另一个设置DLL的函数以供进一步使用:

过程设置\u dll;stdcall;导出;
开始
com1:=t导入.创建(无);
结束;
有另一个破坏它的:

过程清理\u dll;stdcall;导出;
开始
com1.免费;
com1:=零;
结束;

在使用DLL的其他函数之前和之后调用这些函数。

+1。您可能需要编辑以解释应该将
stdcall
添加到所有导出的过程声明中(因为询问者明确表示他们不熟悉Delphi)。非常好的编辑。:)如果可以,我会给它一个额外的+1。(我只想更改“不幸”和“不受支持”这两个词,因为在大多数情况下,当您编写本机Win32应用程序时,
fastcall
register
是最佳选择-您可以说微软选择
stdcall
作为默认值是“不幸的”因为当没有以某种方式使用时,它不如
fastcall
高效。)Delphi的主要用途是开发独立的、自包含的Win32可执行文件,并且目标函数使用
fastcall
register
调用约定最有效尽管正确的调用约定很重要,但在这种情况下,它不应该成为问题的原因。当没有函数参数时,stdcall和register调用约定是相同的。不幸的是,.NET不支持fastcall/register,因此,您不能使用更明显的选项并修复导入以匹配Delphi导出。所有这些调用约定的讨论都非常有趣,但与一个关于无参数过程的问题完全无关。当然,您可以使用纯C#来实现这一点,从而避免Pinvoke和额外的本机ModuleThaks。今晚我将尝试使用它来看看会发生什么:)