2010-07-16 78 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

相关问题