2012-02-02 11 views
3

C#からDelphi 7のDLLファイルを呼び出す際に問題が発生しました。私はC#の初心者です。Delphiについてはあまり知らないので、それほど大したことは分かりません。私はこの問題をできるだけ早く解決する必要があります。"保護されたメモリを読み書きしようとしました。これは他のメモリが壊れていることを示すことがよくあります。 Delphi7 DLL from 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(); 
     } 
    } 
} 

すべてのヘルプは本当に

+0

delphiタグを追加する必要があります。 –

+0

'com1'または' comport1'ですか? –

+1

確かに純粋なC#でこれを行うことができ、従ってpinvokesと余分なネイティブモジュール –

答えて

7

EDITを理解されるであろう:

さらなるリフレクションをすると、これは正しい答えではないと私は確信しています。それはまだ不一致の呼び出し規約(これは私の最初の本能それが問題だった)を使用するためにはまだ悪い考えですが、このケースではおそらくGPFの原因ではありません。

ORIGINAL:時間の

99%、このエラーは、呼び出し規約が間違ってましたことを意味します。私はDelphiで書いたので、それはしばらくしているが、私は、これはあなたの問題を解決すると思います:

procedure moveforward; export; stdcall; 

calling conventionは、通常、あなただけの単一のコンパイラを使用している問題ではない、すべてが同じものを使用しているため。言語を混在させたり、異なるベンダーのコンパイラを混在させても、問題になる可能性があります。呼び出し規約によって、呼び出しの最後にパラメータをクリーンアップする必要があります。両方の側がそれをしようとすると、GPFが発生する可能性があります。

デフォルトでは、DllImport属性の呼び出し規約はCallingConvention.StdCallですが、属性自体でオーバーライドできます。残念ながら、Delphiのデフォルトの呼び出し規約は、サポートされていないタイプ(ファストコールまたはレジスタとも呼ばれます)であるため、唯一の選択肢は、Delphi側をstdcallを使用するように変更することです。

+2

+1を避けることができます。あなたは、 'stdcall'がエクスポートされたすべてのプロシージャ宣言に追加されるべきであることを説明するために編集したいと思うかもしれません(アスカーがDelphiに慣れていないと具体的に言っているので)。 –

+3

**非常に**素敵な編集。 :)もし私ができるなら、私はそれに余分な+1を与えるだろう。 (私はネイティブのWin32アプリケーションをプログラミングしているとき、ほとんどの状況で 'fastcall'や' register'が最良の選択であるため、「残念なことに」と「サポートされていません」という言葉だけを変更します。Microsoftの 'stdcall Delphiの主な用途は、スタンドアローンの自己完結型のWin32実行可能ファイルを開発することであり、その目的は、 '' fastcall'または 'register'呼び出し規約に従います。 :) –

+1

呼び出し規約を正しくすることは重要ですが、この場合は問題の原因ではありません。関数の引数がない場合、stdcallとregisterの呼び出し規約は同じです。 –

5

Delphiコードは、変数com1に値を割り当てません。あなたはTComportインスタンスを参照する必要があります。さらに使用するためにDLLを設定し、別の関数をエクスポートします。

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

呼び出し、それらの機能の前およびDLLの他の機能を使用した後:

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

は、それを破壊する別のものを持っています。

+0

ありがとうございました。何が起こるかを見てみましょう:) – user1184061

関連する問題