[英]Pointer in managed Code? C#
我使用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作为指针,但它会产生错误。 这不可能吗?
在方法声明中使用ref:
[DllImport(DLLPath, CallingConvention = CallingConvention.Cdecl)]
public extern static int AMRecoveryModeDeviceReboot(
ref AMRecoveryDevice device,
byte[] paramByte,
int u1,
int u2,
int u3)
使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杂志:
将其他所有内容保持不变,您只需将struct
更改为class
。
正如您指定的顺序布局,这将表现得像指向结构的指针。
IOW:
[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)
我通常使用的模式是将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); }
}
如果你在不安全的环境中工作,那就没有了。 请参阅: http : //msdn.microsoft.com/en-us/library/chfa2zb8(VS.71).aspx
但是不建议在托管应用程序中使用。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.