2012-02-02 104 views
3

我正面临从C#调用Delphi 7 DLL文件的问题。我是C#的新手,不太了解Delphi,而且我不需要非常了解这些。我只需要尽快解决这个问题。“尝试读取或写入受保护的内存,这通常表示其他内存已损坏。”来自C#的Delphi7 DLL

我想从C#调用dll,但出现此错误:“尝试读取或写入受保护的内存,这通常表示其他内存已损坏。”

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

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

任何帮助将真正的赞赏

+0

你应该添加一个delphi标签。 – 2012-02-02 01:37:27

+0

'com1'或'comport1'? – 2012-02-02 03:06:31

+1

当然,你可以用纯C#做这个,从而避免pinvokes和额外的本地模块 – 2012-02-02 07:49:16

回答

7

编辑:

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

ORIGINAL:时间

99%,这个错误意味着你得到了调用约定错误。它已经有一段时间,因为我在Delphi写的,但我认为这将解决您的问题:

procedure moveforward; export; stdcall; 

calling convention通常不是当你只使用一个单一的编译器的问题,因为一切都使用相同的一个。当你混合使用语言,或者混用不同供应商的编译器时,这可能会成为问题。调用约定确定呼叫的哪一端必须清理参数;如果双方试图这样做,很可能会导致GPF。

默认情况下,DllImport属性使用调用约定CallingConvention.StdCall,尽管您可以在属性本身中覆盖该约定。不幸的是,Delphi的默认调用约定是一种不被支持的类型(或者称为fastcall或register),所以你唯一的选择是改变Delphi方面来使用stdcall。

+2

+1。您可能想要编辑以解释stdcall应该添加到所有导出的过程声明中(因为提问者明确表示他们不熟悉Delphi)。 – 2012-02-02 02:05:30

+3

**非常好的编辑。 :)如果可以的话,我会给它一个额外的+1。 (我只会改变“不幸”和“不支持”这两个词,因为在你编写原生Win32应用程序时,在大多数情况下,fastcall或register是最好的选择 - 你可以说微软选择了stdcall '因为默认值是“不幸的”,因为它不以'fastcall'的效率不以特定的方式使用。)Delphi的主要用途是开发独立的,独立的Win32可执行文件,并且使用'快速呼叫“或”注册“呼叫约定。 :) – 2012-02-02 02:50:47

+1

尽管正确调用约定很重要,但在这种情况下,它不应该是问题的原因。当没有函数参数时,stdcall和register调用约定是相同的。 – 2012-02-02 03:05:38

5

Delphi代码从不为全局变量com1赋值。您需要使其参考TComport实例。导出设置的DLL进一步使用其他功能:

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

有另外一个,它摧毁:之前和使用DLL的其他功能后

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

调用这些函数。

+0

非常感谢,我会试着看看会发生什么:) – user1184061 2012-02-15 01:59:18

相关问题