2010-07-16 99 views
3

我使用C#.net。託管代碼中的指針? C#

這是現在我的方法:

[DllImport(DLLPath, CallingConvention = CallingConvention.Cdecl)] 
    unsafe public extern static int AMRecoveryModeDeviceReboot(AMRecoveryDevice device, byte[] paramByte, int u1, int u2, int u3) 

我必須對自己的一個指針,AMRecoveryDevice是一個結構:

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)] 
internal struct AMRecoveryDevice 
{ 
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] 
    public byte[] unknown0;  /* 0 */ 
    public DeviceRestoreNotificationCallback callback; /* 8 */ 
    public IntPtr user_info;  /* 12 */ 
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 12)] 
    public byte[] unknown1;  /* 16 */ 
    public uint readwrite_pipe; /* 28 */ 
    public byte read_pipe;   /* 32 */ 
    public byte write_ctrl_pipe; /* 33 */ 
    public byte read_unknown_pipe; /* 34 */ 
    public byte write_file_pipe; /* 35 */ 
    public byte write_input_pipe; /* 36 */ 
}; 

現在我必須AMRecoveryDevice作爲第一種方法的指針,但它會給出一個錯誤。 這不可能嗎?

回答

9

使用裁判在方法聲明:

[DllImport(DLLPath, CallingConvention = CallingConvention.Cdecl)] 
public extern static int AMRecoveryModeDeviceReboot(
    ref AMRecoveryDevice device, 
    byte[] paramByte, 
    int u1, 
    int u2, 
    int u3) 
+0

謝謝你太多了! – Kovu 2010-07-16 10:43:18

4

device一個ref參數:

[DllImport(DLLPath, CallingConvention = CallingConvention.Cdecl)] 
unsafe public extern static int AMRecoveryModeDeviceReboot(
    ref AMRecoveryDevice device, 
    byte[] paramByte, 
    int u1, 
    int u2, 
    int u3) 

如何將數據傳遞到P/Invoke調用一篇好文章是這樣一個從MSDN雜誌:

Jason Clark: P/Invoke Revisited

+0

對於來自Jason的文章+1 +1 – Oliver 2010-07-16 10:55:50

2

保持其他條件相同,您可以將struct更改爲class

由於您已經指定了順序佈局,所以它的行爲就像一個指向結構的指針。

督察:

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)] 
internal class AMRecoveryDevice 
{ 
    ... 
}  

... 

[DllImport(DLLPath, CallingConvention = CallingConvention.Cdecl)] 
extern static int AMRecoveryModeDeviceReboot(AMRecoveryDevice device, 
    byte[] paramByte, int u1, int u2, int u3) 
1

我通常使用的模式是使P /調用聲明私下和地方結構的使用IntPtr。提供公共方法來處理編組。 (你也可以擺脫不安全的這種方式。)

[DllImport(DLLPath, CallingConvention = CallingConvention.Cdecl)] 
private extern static int AMRecoveryModeDeviceReboot(IntPtr device, byte[] paramByte, int u1, int u2, int u3) 

public static int AMRecoveryModeDevice(ref AMRecoveryDevice device, byte[] paramByte, int u1, int u2, int u3) { 
    var ptr = Marshal.AllocHGlobal(Marshal.SizeOf(device)); 
    Marshal.StructureToPointer(device, ptr, false); 
    int result = AMRecoveryModeDeviceReboot(ptr, paramByte, u1, u2, u3); 
    device = (AMRecoveryDevice)Marshal.PtrToStructure(ptr, typeof(AMRecoveryDevice)); 
    Marshal.FreeHGlobal(ptr); 
    return result; 
} 

爲了您AMRecoveryDevice結構,你應該使用一個IntPtr回調委託過。

[MarshalAs(UnmanagedType.FunctionPtr)] 
private IntPtr _callback; /* 8 */ 
public DeviceRestoreNotificationCallback callback { 
    get { return (DeviceRestoreNotificationCallback)Marsal.GetDelagateFromFunctionPointer(_callback, typeof(DeviceRestoreNotificationCallback)); } 
    set { _calback = Marshal.GetFunctionPointerFromDelegate(value); } 
} 
+0

這可以工作,但是工作更多,因爲它需要手動封送。 – 2010-07-16 13:33:53