NETCF كيف يمكنني تمرير البنية حسب المرجع إلى DeviceIoControl
-
11-12-2019 - |
سؤال
أنا جديد على إطار العمل المضغوط .NET.أحتاج إلى استدعاء وظيفة DeviceIoControl وتمرير الهياكل كمعلمات الإدخال والإخراج إلى وظيفة IOControl.
في PInvoc/DeviceIoControl لقد وجدت كيفية الوصول إلى الوظيفة نفسها.ولكن كيف يمكنني تمرير مؤشر البنية كما InBuf
و OutBuf
معامل؟
يتم تعريف DeviceIoControl على أنه P/Invoc:
[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 التي تتوقع أن يكون المؤشر بايتًا بدلاً من مرجع البنية؟
المحلول
تكمن المشكلة في أن إعلان P/Invention الخاص بك لا يتطابق مع مكالمتك.يأخذ DeviceIoControl مؤشرات لمعلمات الدخول/الخروج:
BOOL DeviceIoControl(
HANDLE hDevice,
DWORD dwIoControlCode,
LPVOID lpInBuffer,
DWORD nInBufferSize,
LPVOID lpOutBuffer,
DWORD nOutBufferSize,
LPDWORD lpBytesReturned,
LPOVERLAPPED lpOverlapped
);
لذلك يمكنك "تعديل" إعلانك بعدة طرق.يستخدم الرابط الموجود في الرابط الذي تقدمه ملف byte[]
ربما من أجل الراحة حيث كانوا يستخدمونه.في حالتك، نظرًا لأنك تمرر بنيات بسيطة (أيلا توجد مؤشرات داخلية لبيانات أخرى)، فإن "الإصلاح" الأسهل هو مجرد تغيير إعلان P/Invoc:
[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);
ويجب أن تعمل التعليمات البرمجية الخاصة بك.لاحظ أنني قمت أيضًا بتغيير أنواع المعلمتين الأوليين للسماح بجعل رمز الاتصال الخاص بك أكثر وضوحًا بدون تحويلات.
تحرير 2
إذا وجدت أنك بحاجة إلى توقيعات مختلفة، فما عليك سوى تحميل ملف P/Invoc.على سبيل المثال، إطار الأجهزة الذكية يحتوي الكود على 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);