«Попытка чтения или записи защищенной памяти. Это часто свидетельствует о повреждении другой памяти».Delphi7 DLL из C # - PullRequest
4 голосов
/ 02 февраля 2012

Я столкнулся с проблемой вызова DLL-файла Delphi 7 из C #. Я новичок в C # и не знаю Delphi так много, и мне не нужно знать, действительно, много. Мне просто нужно решить эту проблему как можно скорее.

Я пытаюсь вызвать dll из C #, но получаю эту ошибку: «Попытка чтения или записи защищенной памяти. Это часто указывает на то, что другая память повреждена».

И я понятия не имею, почему это происходит. Как вы увидите в моем коде Delphi, я не пытаюсь вернуть какое-либо значение. Мне просто нужно отправить несколько команд на COM-порт. Пожалуйста, если кто-нибудь может помочь мне отсюда: (

Код DLL Delphi:

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

Любая помощь будет по достоинству оценена

Ответы [ 2 ]

7 голосов
/ 02 февраля 2012

РЕДАКТИРОВАТЬ:

Обратите внимание, что при дальнейшем размышлении я почти уверен, что это неправильный ответ. все еще плохая идея использовать несоответствующие соглашения о вызовах (таким образом, мой первоначальный инстинкт, что это была проблема), но в этом случае это, вероятно, не причина GPF.

ОРИГИНАЛ:

99% времени, эта ошибка означает, что вы неправильно поняли правила вызова. Прошло много времени с тех пор, как я написал в Delphi, но я думаю, что это решит вашу проблему:

procedure moveforward; export; stdcall;

Соглашение о вызовах обычно не является проблемой, когда вы используете только один компилятор, потому что все используют один и тот же. Это может быть проблемой, когда вы смешиваете языки, или даже если вы смешиваете компиляторы разных поставщиков. Соглашение о вызовах определяет, какой конец вызова должен очистить параметры; если обе стороны попытаются это сделать, это может привести к GPF.

По умолчанию атрибут DllImport использует соглашение о вызовах CallingConvention.StdCall, хотя вы можете переопределить его в самом атрибуте. К сожалению, соглашение о вызовах по умолчанию в Delphi - это тип, который не поддерживается (альтернативно называемый fastcall или register), поэтому единственный вариант - изменить сторону Delphi для использования stdcall.

5 голосов
/ 02 февраля 2012

Код Delphi никогда не присваивает значение глобальной переменной com1. Вам нужно сделать так, чтобы он ссылался на экземпляр TComport. Экспортируйте другую функцию, которая настраивает DLL для дальнейшего использования:

procedure set_up_dll; stdcall; export;
begin
  com1 := TComport.Create(nil);
end;

Есть еще один, который уничтожает его:

procedure clean_up_dll; stdcall; export;
begin
  com1.Free;
  com1 := nil;
end;

Вызывайте эти функции до и после использования других функций DLL.

...