2012-02-02 105 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

相關問題