Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/309.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在C中作为参数传递包含数组的结构指针# 我有C++的功能,在DLL中导出。 功能是 LONG LOGIN(LPDEVINFO info);_C#_Pinvoke_Dllimport - Fatal编程技术网

C# 在C中作为参数传递包含数组的结构指针# 我有C++的功能,在DLL中导出。 功能是 LONG LOGIN(LPDEVINFO info);

C# 在C中作为参数传递包含数组的结构指针# 我有C++的功能,在DLL中导出。 功能是 LONG LOGIN(LPDEVINFO info);,c#,pinvoke,dllimport,C#,Pinvoke,Dllimport,LPDEVINFO的结构是: struct{ BYTE sSerialNumber[20]; } *LPDEVINFO; 为了传递LPDEVINFO参数,我在托管代码中定义了一个类: class DEVINFO{ Byte[] sSerialNumber = new Byte[20]; } 然后像这样p/Invoke: [DllImport ('MyDll.dll')] public static extern Int32 LOGIN(DEVINFO info);

LPDEVINFO
的结构是:

struct{  
       BYTE sSerialNumber[20];
} *LPDEVINFO;
为了传递
LPDEVINFO
参数,我在托管代码中定义了一个类:

class DEVINFO{
     Byte[] sSerialNumber = new Byte[20];
}
然后像这样p/Invoke:

[DllImport ('MyDll.dll')]
public static extern Int32 LOGIN(DEVINFO info);
然后用C#来称呼它:

运行此代码时,出现以下错误:

An unhandled exception of type 'System.AccessViolationException' occurred in WindowsFormsApplication1.exe

Additional information: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
我认为问题是由数组
sSerialNumber
引起的。但我不知道如何用正确的方式来定义它


提前谢谢

使用
fixed
关键字声明包含固定大小缓冲区的结构:

public unsafe struct DevInfo
{
    public fixed byte sSerialNumber[20];
}
有关详细信息,请参阅

另外,要通过指针传递结构(对应于本机端的
LPDEVINFO
),请按如下方式声明函数:

[DllImport ('MyDll.dll')]
public static extern Int32 LOGIN(ref DevInfo info);
并称之为:

DevInfo info = new DevInfo();
int id = LOGIN(ref info)

使用
fixed
关键字声明包含固定大小缓冲区的结构:

public unsafe struct DevInfo
{
    public fixed byte sSerialNumber[20];
}
有关详细信息,请参阅

另外,要通过指针传递结构(对应于本机端的
LPDEVINFO
),请按如下方式声明函数:

[DllImport ('MyDll.dll')]
public static extern Int32 LOGIN(ref DevInfo info);
并称之为:

DevInfo info = new DevInfo();
int id = LOGIN(ref info)

函数需要指向结构的指针,而不是实际结构的指针

使用Marshal.StructureToPtr()函数将结构转换为IntPtr

C#中的示例:

如果这是一个OUT参数,即调用函数后需要从中读取,因为被调用方对其进行了修改,然后使用Marshal.PtrToStructure将其读回托管结构,如下所示:

DEVINFO info = (DEVINFO)Marshal.PtrToStructure(infoPtr, typeof(DEVINFO));

函数需要指向结构的指针,而不是实际结构的指针

使用Marshal.StructureToPtr()函数将结构转换为IntPtr

C#中的示例:

如果这是一个OUT参数,即调用函数后需要从中读取,因为被调用方对其进行了修改,然后使用Marshal.PtrToStructure将其读回托管结构,如下所示:

DEVINFO info = (DEVINFO)Marshal.PtrToStructure(infoPtr, typeof(DEVINFO));

我会在这里使用
UmanagedType.ByValArray

class DEVINFO {
    [MarshalAs(UnmanagedType.ByValArray, SizeConst=20)]
    public byte[] sSerialNumber;
}

否则我觉得一切都很好。特别是,使用
类而不是
结构来实现这一点非常好,我将在这里使用
UmanagedType.ByValArray

class DEVINFO {
    [MarshalAs(UnmanagedType.ByValArray, SizeConst=20)]
    public byte[] sSerialNumber;
}


否则我觉得一切都很好。特别是,使用<代码>类<代码>,而不是<代码>结构> <代码> > < /p>如果“代码>长< /C>”被定义为C++中的64位整数类型,则必须将函数导出为<代码> ExtIn 64登录(DeViFielo信息);代码>或
外部长登录(DEVINFO info)。至于您的
DEVINFO
类,我将使其成为一个结构,并将属性
[MarshalAs(UnmanagedType.ByValArray,SizeConst=20)]
应用于字节数组@吉姆<代码>长< /Cord>是Windows上C和C++的32位整数。我不知道为什么会这样。@Jim这是一个非常常见的陷阱,
LONG
LONG
相同,在Windows上是32位的C。在C<代码>长< /COD>是64位。谢谢@ JimSuuBube,[ MarshalAs(unMaundType,ByValSalm,SsieCuSt= 20)]为我工作。如果<代码>长< /C> >被定义为C++中的64位整数类型,则必须将函数导出为<代码> ExtIn 64登录(DeViFielo信息);<代码>或
外部长登录(DEVINFO info)。至于您的
DEVINFO
类,我将使其成为一个结构,并将属性
[MarshalAs(UnmanagedType.ByValArray,SizeConst=20)]
应用于字节数组@吉姆<代码>长< /Cord>是Windows上C和C++的32位整数。我不知道为什么会这样。@Jim这是一个非常常见的陷阱,
LONG
LONG
相同,在Windows上是32位的C。在C#
中,long
是64位。感谢@JimSchubert,[marshallas(UnmanagedType.ByValArray,SizeConst=20)]对我有用。根据问题中的代码,使用
类而不是struct意味着将传递指针。这不是问题,布拉德利的答案更好。我只是习惯于在奇怪的互操作场景中使用StructureToPtr,比如指向指向结构的指针数组的指针,在这些场景中,简单的ref功能是不够的。使用
class
就可以了。我一直这么做。关键是这个事实使得你的答案的全部内容无效。根据问题中的代码,使用
类而不是struct意味着将传递一个指针。这不是问题,布拉德利的答案更好。我只是习惯于在奇怪的互操作场景中使用StructureToPtr,比如指向指向结构的指针数组的指针,在这些场景中,简单的ref功能是不够的。使用
class
就可以了。我一直这么做。关键是这个事实使得你的答案的全部内容无效。我对这个答案的否决票和布拉德利答案的否决票感到困惑。我看不出他们俩有什么问题。如果有什么不对劲,我想纠正它。我对这个答案的否决票和布拉德利答案的否决票感到困惑。我看不出他们俩有什么问题。如果有什么问题,我想纠正它。关键字“fixed”,我得到错误CS0214:指针和固定大小的缓冲区只能在不安全的环境中使用context@englefly您可能需要在struct声明(修改了我的答案)和(可能)使用它的代码中添加
unsafe
。您还需要在C#项目属性中启用不安全代码。使用关键字“fixed”,我得到错误CS0214:指针和固定大小的缓冲区只能在不安全的环境中使用context@englefly您可能需要在struct声明(修改了我的答案)和(可能)使用它的代码中添加
unsafe
。您还需要在C#项目属性中启用不安全代码。