2010-02-12 66 views
2

我想在C#相当于写入以下内容:如何通过Pinvoke将指针传递给结构?

typedef struct BATT_ID 
{ 
    UINT8  nBattID[8]; 
} BATT_ID, *PBATT_ID; 

HANDLE g_hDevice; 

// Connect to the driver 
g_hDevice = CreateFile(L"BAT1:", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); 

void GetBattID(PBATT_ID pBattId) 
{ 
    // ... snipped code to check g_hDevice is valid ... 

    DeviceIoControl(g_hDevice, SOMO650_PWR_GET_BATT_ID, NULL, 0, pBattId, sizeof(BATT_ID), dwByteReturn, NULL)) 
} 

// once BATT_ID has been filled it can be formatted as follows 
wsprintf(strInfo, TEXT("%02X:%02X:%02X:%02X:%02X:%02X"), BattID.nBattID[6], BattID.nBattID[5], BattID.nBattID[4], BattID.nBattID[3], BattID.nBattID[2], BattID.nBattID[1]); 

的代码连接到Windows Mobile设备的功率驱动器,并试图找回的电池ID。
这是SoMo650和Socket的最新ROM版本只能在C.提供的示例代码

我可以成功所做的一切(是最好的,我可以告诉)除了呼吁DeviceIoControl的,因为我不知道如何将BATT_ID结构转换为C#。

我猜测,因为它是一个结构和DeviceIoControl期望一个指针,我应该看着Marshal.PtrToStructure(),但我有很少的C经验,感觉非常深刻。

任何援助将不胜感激。

回答

5

你可能更好地使用Smart Device Framework,它有一个电池控制的地方..看这里的社区版下载链接。

编辑:如果你还是想PInvoke的等效结构看这里:

 
[StructLayout(LayoutKind.Sequential, Pack = 1)] 
public struct BATT_ID 
{ 
    [System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.ByValArray, SizeConst = 8, ArraySubType = System.Runtime.InteropServices.UnmanagedType.I8)] 
     public int[] nBattId; 
}; 

然后之前的P /调用,您需要为“DeviceIoControl”签名如下所示:

 
[DllImport("coredll.dll", EntryPoint="DeviceIoControl", SetLastError=true)] 
     internal static extern int DeviceIoControlCE(
      int hDevice, 
      int dwIoControlCode, 
      byte[] lpInBuffer, 
      int nInBufferSize, 
      byte[] lpOutBuffer, 
      int nOutBufferSize, 
      ref int lpBytesReturned, 
      IntPtr lpOverlapped); 

呼叫是这样的:

 
IntPtr ptr = IntPtr.Zero; 
BATT_ID battId; 
int sz = Marshal.SizeOf(battId.GetType()); 
ptr = Marshal.AllocHGlobal(sz); 
Marshal.StructureToPtr((BATT_ID)battId, ptr, false); 
byte[] pBattId = ptr.ToPointer(); 
out int bytesReturned = 0; 
DeviceIoControl(handle, IOCONTROL_ID, null, 0, pBattId, sz, ref bytesReturned, IntPtr.Zero); 
battId = Marshal.PtrToStructure(ptr, battId.GetType()); 
Marshal.FreeHGlobal(ptr); 

我希望我有这个权利......

编辑#2:作为ctacke指出我的代码示例是错误的...

 
unsigned byte[8] battId; 
DeviceIoControl(g_hDevice, SOMO650_PWR_GET_BATT_ID, null, 0, battId, Marshal.SizeOf(battId), ref bytesReturned, IntPtr.Zero); 
+0

SDF提供的电池相关功能是GetSystemPowerStatusEx2上的一个包装。我试图获得的信息只能从设备驱动程序中获得。 – 2010-02-12 15:21:13

+0

@Matt:好的,看看编辑的答案我希望我有正确的方式.... :) – t0mm13b 2010-02-12 15:31:51

+0

你的结构是不正确的 - 原始定义是8 UINT8's,它只是8个字节。也不需要把它包装在一个结构中(即使它是8个整数)。 – ctacke 2010-02-12 15:49:39

3

基本上你(谢谢!)有一个8字节的结构。只需传递8字节的byte []给DeviceIoControl调用即可。无需调用AllocHGlobal,或执行任何其他古怪的编组。