代码之家  ›  专栏  ›  技术社区  ›  PassionateDeveloper

托管代码中的指针?C级#

c#
  •  3
  • PassionateDeveloper  · 技术社区  · 14 年前

    我使用C#net。

    我现在的方法是:

        [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作为指针,但是它会给出一个错误。 不可能吗?

    5 回复  |  直到 14 年前
        1
  •  9
  •   arbiter    14 年前

    [DllImport(DLLPath, CallingConvention = CallingConvention.Cdecl)]
    public extern static int AMRecoveryModeDeviceReboot(
        ref AMRecoveryDevice device,
        byte[] paramByte,
        int u1,
        int u2,
        int u3)
    
        2
  •  4
  •   Dirk Vollmar    14 年前

    制造 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

        3
  •  2
  •   leppie    14 年前

    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)
    
        4
  •  1
  •   Mark H    14 年前

    我通常使用的模式是将P/invoke声明私有化并使用 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); }
    }
    
        5
  •  0
  •   Laurens Ruijtenberg    14 年前

    http://msdn.microsoft.com/en-us/library/chfa2zb8(VS.71).aspx

    但不建议在托管应用程序中使用。