使用非托管 C++ DLL 的 AccessViolationException
AccessViolationException using unmanaged C++ DLL
我第一次尝试在 C# 应用程序中使用非托管 C++ DLL ("res_lib")。我已使用 cppsharp 生成 PInvoke 代码:例如,我尝试调用的 functions/methods 之一是 get_system_snapshot
。在 .h
文件中,这被定义为
SYS_INT SYS_ERR get_system_snapshot(SNAPSHOT_PARMS* snapshotp);
SYS_INT
和 SYS_ERR
等同于 int32_t
。 SNAPSHOT_PARMS
是
typedef struct SNAPSHOT_PARMS
{
SYS_ULONG size;
SYS_UINT count;
SYS_CHAR serial_no[600];
} SYS_PACK_DIRECTIVE SYS_SNAPSHOT_PARMS;
cppsharp 已将其转换为以下代码片段:
DllImport
[SuppressUnmanagedCodeSecurity]
[DllImport("res_lib", CallingConvention = CallingConvention.StdCall,
EntryPoint="get_system_snapshot")]
internal static extern int GetSystemSnapshot(IntPtr snapshotp);
对象
public unsafe partial class SNAPSHOT_PARMS : IDisposable
{
[StructLayout(LayoutKind.Explicit, Size = 608)]
public partial struct __Internal
{
[FieldOffset(0)]
internal uint size;
[FieldOffset(4)]
internal uint count;
[FieldOffset(8)]
internal fixed sbyte serial_no[600];
[SuppressUnmanagedCodeSecurity]
[DllImport("res_lib", CallingConvention = global::System.Runtime.InteropServices.CallingConvention.ThisCall,
EntryPoint="??0SNAPSHOT_PARMS@@QAE@ABU0@@Z")]
internal static extern global::System.IntPtr cctor(global::System.IntPtr instance, global::System.IntPtr _0);
}
}
public SNAPSHOT_PARMS()
{
__Instance = Marshal.AllocHGlobal(sizeof(global::res_lib.SNAPSHOT_PARMS.__Internal));
__ownsNativeInstance = true;
NativeToManagedMap[__Instance] = this;
}
主要代码
static void Main(string[] args)
{
SNAPSHOT_PARMS p = new SNAPSHOT_PARMS();
var result = res_lib.res_lib.GetSystemSnapshot(p);
}
public static unsafe int GetSystemSnapshot(global::res_lib.SNAPSHOT_PARMS snapshotp)
{
var __arg0 = ReferenceEquals(snapshotp, null) ? global::System.IntPtr.Zero : snapshotp.__Instance;
var __ret = __Internal.GetSystemSnapshot(out __arg0);
return __ret;
}
调用函数时,我得到了臭名昭著的:
Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
我尝试将 CallingConvention
从 StdCall
更改为 Cdecl
,将 [In]
和 [Out]
引入 DllImport
等,但都无济于事。任何人都可以看出代码有任何明显的错误吗 - 很明显,这对我来说是全新的,也许我对 cppsharp 生成不需要调整的代码的要求有点高。
EDIT 原始 C++ 文档有一个示例,其中结构由
初始化
#define INIT_STRUCT(struct_p) { memset(struct_p, 0, sizeof(*(struct_p))); (struct_p)->size = sizeof(*(struct_p)); }
并被使用
SNAPSHOT_PARMS snapshot_parms;
SYS_ERR result;
INIT_STRUCT(&snapshot_parms);
result = get_system_snapshot(&snapshot_parms);
根据 C++ 声明,这应该足够了:
[StructLayout(LayoutKind.Sequential)]
unsafe struct SNAPSHOT_PARMS {
public int size;
public int count;
public fixed byte serial_no[600];
}
[DllImport("res_lib", EntryPoint = "get_system_snapshot")]
static extern int GetSystemSnapshot(ref SNAPSHOT_PARMS snapshot);
用作
var s = new SNAPSHOT_PARMS { size = Marshal.SizeOf<SNAPSHOT_PARMS>() };
int result = GetSystemSnapshot(ref s);
// check result, use s
我第一次尝试在 C# 应用程序中使用非托管 C++ DLL ("res_lib")。我已使用 cppsharp 生成 PInvoke 代码:例如,我尝试调用的 functions/methods 之一是 get_system_snapshot
。在 .h
文件中,这被定义为
SYS_INT SYS_ERR get_system_snapshot(SNAPSHOT_PARMS* snapshotp);
SYS_INT
和 SYS_ERR
等同于 int32_t
。 SNAPSHOT_PARMS
是
typedef struct SNAPSHOT_PARMS
{
SYS_ULONG size;
SYS_UINT count;
SYS_CHAR serial_no[600];
} SYS_PACK_DIRECTIVE SYS_SNAPSHOT_PARMS;
cppsharp 已将其转换为以下代码片段:
DllImport
[SuppressUnmanagedCodeSecurity]
[DllImport("res_lib", CallingConvention = CallingConvention.StdCall,
EntryPoint="get_system_snapshot")]
internal static extern int GetSystemSnapshot(IntPtr snapshotp);
对象
public unsafe partial class SNAPSHOT_PARMS : IDisposable
{
[StructLayout(LayoutKind.Explicit, Size = 608)]
public partial struct __Internal
{
[FieldOffset(0)]
internal uint size;
[FieldOffset(4)]
internal uint count;
[FieldOffset(8)]
internal fixed sbyte serial_no[600];
[SuppressUnmanagedCodeSecurity]
[DllImport("res_lib", CallingConvention = global::System.Runtime.InteropServices.CallingConvention.ThisCall,
EntryPoint="??0SNAPSHOT_PARMS@@QAE@ABU0@@Z")]
internal static extern global::System.IntPtr cctor(global::System.IntPtr instance, global::System.IntPtr _0);
}
}
public SNAPSHOT_PARMS()
{
__Instance = Marshal.AllocHGlobal(sizeof(global::res_lib.SNAPSHOT_PARMS.__Internal));
__ownsNativeInstance = true;
NativeToManagedMap[__Instance] = this;
}
主要代码
static void Main(string[] args)
{
SNAPSHOT_PARMS p = new SNAPSHOT_PARMS();
var result = res_lib.res_lib.GetSystemSnapshot(p);
}
public static unsafe int GetSystemSnapshot(global::res_lib.SNAPSHOT_PARMS snapshotp)
{
var __arg0 = ReferenceEquals(snapshotp, null) ? global::System.IntPtr.Zero : snapshotp.__Instance;
var __ret = __Internal.GetSystemSnapshot(out __arg0);
return __ret;
}
调用函数时,我得到了臭名昭著的:
Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
我尝试将 CallingConvention
从 StdCall
更改为 Cdecl
,将 [In]
和 [Out]
引入 DllImport
等,但都无济于事。任何人都可以看出代码有任何明显的错误吗 - 很明显,这对我来说是全新的,也许我对 cppsharp 生成不需要调整的代码的要求有点高。
EDIT 原始 C++ 文档有一个示例,其中结构由
初始化#define INIT_STRUCT(struct_p) { memset(struct_p, 0, sizeof(*(struct_p))); (struct_p)->size = sizeof(*(struct_p)); }
并被使用
SNAPSHOT_PARMS snapshot_parms;
SYS_ERR result;
INIT_STRUCT(&snapshot_parms);
result = get_system_snapshot(&snapshot_parms);
根据 C++ 声明,这应该足够了:
[StructLayout(LayoutKind.Sequential)]
unsafe struct SNAPSHOT_PARMS {
public int size;
public int count;
public fixed byte serial_no[600];
}
[DllImport("res_lib", EntryPoint = "get_system_snapshot")]
static extern int GetSystemSnapshot(ref SNAPSHOT_PARMS snapshot);
用作
var s = new SNAPSHOT_PARMS { size = Marshal.SizeOf<SNAPSHOT_PARMS>() };
int result = GetSystemSnapshot(ref s);
// check result, use s