2012-05-18 1 views
2

Я новичок в .NET compact framework. Мне нужно вызвать функцию DeviceIoControl и передать структуры в качестве входных и выходных параметров функции IOControl.NETCF как передать структуру по ссылке на DeviceIoControl

В PInvoke/DeviceIoControl Я нашел, как получить доступ к самой функции. Но как я могу передать указатель на структуру как InBuf и OutBuf параметр?

DeviceIoControl определяется как P/Invoke:

[DllImport("coredll", 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); 

структуры в вопросе есть этот макет:

struct Query 
{ 
    int a; 
    int b; 
    char x[8]; 
} 

struct Response 
{ 
    int result; 
    uint32 success; 
} 

void DoIoControl() 
{ 
    Query q = new Query(); 
    Response r = new Response(); 
    int inSize = System.Runtime.InteropServices.Marshal.SizeOf(q); 
    int outSize = System.Runtime.InteropServices.Marshal.SizeOf(r); 
    NativeMethods.DeviceIoControlCE((int)handle, (int)IOCTL_MY.CODE, 
    ref q, inSize, ref r, outSize, ref bytesReturned, IntPtr.Zero); 
} 

Редактировать: Когда я пытаюсь скомпилировать этот код я получаю ошибка:

cannot convert from 'ref MyNamespace.Response' to 'byte[]' 

Как передать адрес структуры функции DeviceIoControl, которая ожидает указатель на байт вместо struct ref?

ответ

2

Проблема в том, что ваше объявление P/Invoke не соответствует вашему вызову. DeviceIoControl принимает указатели для в/из paramters:

BOOL DeviceIoControl(
    HANDLE hDevice, 
    DWORD dwIoControlCode, 
    LPVOID lpInBuffer, 
    DWORD nInBufferSize, 
    LPVOID lpOutBuffer, 
    DWORD nOutBufferSize, 
    LPDWORD lpBytesReturned, 
    LPOVERLAPPED lpOverlapped 
); 

Таким образом, вы можете «настроить» Ваше заявление во многих отношениях. В приведенной ссылке используется byte[], вероятно, для удобства, когда они ее использовали. В вашем случае, так как вы не проходя простые структуры (то есть никакие внутренние указателей на другие данные), то проще «исправить», чтобы просто изменить вас P/Invoke заявления:

[DllImport("coredll", SetLastError = true)]  
internal static extern int DeviceIoControl( 
    IntPtr hDevice, 
    IOCTL.MY dwIoControlCode,  
    ref Query lpInBuffer, 
    int nInBufferSize,  
    ref Response lpOutBuffer, 
    int nOutBufferSize,  
    ref int lpBytesReturned, 
    IntPtr lpOverlapped);  

И код должны работать. Примечание. Я также изменил типы первых двух параметров, чтобы сделать код вызова более понятным без приведения.

EDIT 2

Если вы обнаружили, что нужны разные подписи, просто перегрузить P/Invoke. Например, код Smart Device Framework имеет как минимум 11 перегрузок для DeviceIoControl. Вот лишь некоторые из них, чтобы дать вам вкус:

[DllImport("coredll.dll", EntryPoint = "DeviceIoControl", SetLastError = true)] 
    internal static extern int DeviceIoControl<TInput, TOutput>(
     IntPtr hDevice, 
     uint dwIoControlCode, 
     ref TInput lpInBuffer, 
     int nInBufferSize, 
     ref TOutput lpOutBuffer, 
     int nOutBufferSize, 
     out int lpBytesReturned, 
     IntPtr lpOverlapped) 
     where TInput : struct 
     where TOutput : struct; 

    [DllImport("coredll.dll", EntryPoint = "DeviceIoControl", SetLastError = true)] 
    internal unsafe static extern int DeviceIoControl(
     IntPtr hDevice, 
     uint dwIoControlCode, 
     void* lpInBuffer, 
     int nInBufferSize, 
     void* lpOutBuffer, 
     int nOutBufferSize, 
     out int lpBytesReturned, 
     IntPtr lpOverlapped); 

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

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

Крис, я включил код, чтобы проиллюстрировать, что я хочу, но пропустил актуальный вопрос. Теперь я надеюсь, что я вообще не назвал эту функцию, поскольку я получаю ошибки компилятора. – harper

+0

Спасибо. Я проверю это, когда вернусь. Но функции ioctl предназначены для выполнения множества разных вызовов, зависящих от кода. Для каждого кода структура inBuf и outBuf может измениться. Поэтому для следующего кода мне нужен другой тип. C++ позволит объединить то, что C# не делает. Как мне обрабатывать различные типы in/outBuf? – harper

+0

Используйте различные объявления P/Invoke, по сути, много перегрузок. Я обновляю свой ответ несколькими из Smart Device Framework. – ctacke

Смежные вопросы