2009-05-07 8 views
6

私はCのDLLをインポートC#プロジェクトを持って、dllがこの機能を持っています渡すポインタ

int primary_read_serial(int handle, int *return_code, int *serial, int length); 

私はシリアルパラメータへのアクセスを取得したいです。私は実際にシリアルパラメータの1文字を返すようにしましたが、私は何をしているのか、何が起こっているのか理解したいとは思っていません。

私は、DLLがアクセスされていること、ポインタのない他の関数がうまく動作していることを確信しています。ポインタをどのように扱うのですか?私はそれをマーシャリングする必要がありますか?データを置く場所を固定しなければならないのでしょうか?

説明は素晴らしいでしょう。

ありがとうございます! リチャード

答えて

8

IntPtrを使用してIntPtrを組み込みたいC#構造体にマーシャリングする必要があります。その場合は、int []にマーシャリングする必要があります。

これは、いくつかのステップで行われます。

  • は、配列をintに管理されたバイト配列
  • 変換バイト配列に配列を変換しunamanged配列
  • で関数を呼び出して管理されていないハンドル
  • を割り当て
  • アンマネージドハンドルのリリース

このコードはあなたのアイデアを与える必要があります。

// The import declaration 
[DllImport("Library.dll")] 
public static extern int primary_read_serial(int, ref int, IntPtr, int) ; 


// Allocate unmanaged buffer 
IntPtr serial_ptr = Marshal.AllocHGlobal(length * sizeof(int)); 

try 
{ 
    // Call unmanaged function 
    int return_code; 
    int result = primary_read_serial(handle, ref return_code, serial_ptr, length); 

    // Safely marshal unmanaged buffer to byte[] 
    byte[] bytes = new byte[length * sizeof(int)]; 
    Marshal.Copy(serial_ptr, bytes, 0, length); 

    // Converter to int[] 
    int[] ints = new int[length]; 
    for (int i = 0; i < length; i++) 
    { 
     ints[i] = BitConverter.ToInt32(bytes, i * sizeof(int)); 
    } 

} 
finally 
{ 
    Marshal.FreeHGlobal(serial_ptr); 
} 

は、try-最後に忘れてはいけない、またはあなたが管理対象外のハンドルをリークが発生する恐れます。あなたのPを書くとき

+0

具体的には、アンマネージ配列とマネージint []とMarshal.Copyをアンマネージド配列のIntPtrを管理対象配列に割り当てます。 –

+1

try-catchまたはtry-finally? – MedicineMan

+0

try-finally、それを指摘してくれてありがとう。一定。 – Coincoin

0

/このようなポインタパラメータのREFキーワードを使用してみてください、その関数の宣言を呼び出す:

[DllImport("YouDll.dll", EntryPoint = "primary_read_serial")] 
public static extern int primary_read_serial(int, ref int, ref int, int) ; 

私はあなたがC#でパラメータ名前を指定する必要がある場合はわかりません。このメソッドを呼び出すときには、参照渡しの引数でrefを使用する必要があります。

+0

配列でなければならないが、IntPtrとMarshalとして渡すことを確認する必要がある。しかし、マネージド配列にコピーする。 –

2

あなたがしようとしていることを理解していれば、これはうまくいくはずです。

unsafe 
{ 
    int length = 1024; // Length of data to read. 

    fixed (byte* data = new byte[length]) // Pins array to stack so a pointer can be retrieved. 
    { 
     int returnCode; 
     int retValue = primary_read_serial(0, &returnCode, data, length); 

     // At this point, `data` should contain all the read data. 
    } 
} 

JaredParはC#は、バックグラウンドであなたのためのマーシャリングを行うように、ちょうどあなたの外部関数の宣言を変更することである、あなたがそれを行うための簡単な方法を提供します。

これは、とにかく少し下のレベルで何が起こっているのかのアイデアを与えることを望みます。

関連する問題