代码之家  ›  专栏  ›  技术社区  ›  KenD Abbas Hadavandi

使用非托管C++ DLL访问Access异常

  •  0
  • KenD Abbas Hadavandi  · 技术社区  · 6 年前

    我第一次尝试在C语言应用程序中使用非托管C++ DLL(RESILILB)。我用过 cppsharp 生成PInvoke代码:例如,我试图调用的函数/方法之一是 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已将其转换为以下代码片段:

    德林波特

    [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;
            }
    

    当调用函数时,我得到了一个臭名昭著的消息:

    我试着改变 CallingConvention StdCall Cdecl ,介绍 [In] [Out] DllImport

    原来的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); 
    
    1 回复  |  直到 6 年前
        1
  •  3
  •   Jeroen Mostert    6 年前

    从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