【问题标题】:System.AccessViolationException when calling function from unmanaged DLL using DLLImport使用 DLLImport 从非托管 DLL 调用函数时出现 System.AccessViolationException
【发布时间】:2019-07-18 09:21:36
【问题描述】:

我正在尝试使用 DLLImport (P/Invoke) 从 C++ DLL 调用函数,但在调用它时不断收到 System.AccessViolationException 错误。请注意,我还有其他功能可以工作。

DLLImport 函数声明:

[DllImport("DocProc.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
        public static extern uint getDPpupTrkBaseConfigPath(DPHandle hdl, StringBuilder str, uint strsize);

用法:

StringBuilder sb = new StringBuilder(256);
                getDPpupTrkBaseConfigPath(handle, sb, (uint)sb.Capacity);

DPHandle:(注意它在其他功能中也有效)

public struct DPHandle
        {
            public uint Size;
            public IntPtr UserHandle;
            [MarshalAs(UnmanagedType.LPStr)] public string DeviceName;
            public uint DeviceTypeId;
            public uint DeviceState;
            public uint OpenFlags;
            public IntPtr Reserved1;
        };

C++:

BPS_PROPL getDPpupTrkBaseConfigPath(DPHandle hdl, char *str, unsigned long strsize);

(注意 BPS_PROPL = unsigned long)

DPHandle:

struct DocProcHandle {
    unsigned long Size;//sizeof(DocProcHandle)
    void* UserHandle;
    const char* DeviceName;
    unsigned long DeviceTypeId;
    unsigned long DeviceState;
    unsigned long OpenFlags;
    void* Reserved1;
};
typedef struct DocProcHandle *DPHandle;

再次,当我尝试调用出现异常的函数时。我尝试查看其他答案,但无法找出问题所在?

【问题讨论】:

  • 您可以尝试不使用StringBuilder 并改用Marshal.AllocHGlobal 吗?还将[MarshalAs(UnmanagedType.LPStr)] public string DeviceName; 更改为public IntPtr DeviceName,看看你是否仍然遇到访问冲突。您是否还验证了 __cdecl 是您的标准调用约定?
  • 尝试获取指向结构的指针并传递它而不是传递结构本身
  • 我不确定使用 IntPtr 代替 StringBuilder 是否可行,因为我希望 C++ 在 StringBuilder 中填充一个字符串。 DPHandle 再次在其他功能中工作,所以我认为这里不是这种情况。是的,我已经验证过了。
  • @SohaibJundi 好的
  • 成功了!将结构更改为 IntPtr 有效!谢谢!

标签: c# c++ pinvoke dllimport


【解决方案1】:

在 C++ 代码中,您有:

typedef struct DocProcHandle *DPHandle;

这意味着DPHandle 是一个指向结构的指针。但是在您的 C# 代码中,您按值传递结构。

实现这一点的最简单方法是将 pinvoke 代码的第一个参数的声明从

DPHandle hdl

[In] ref DPHandle hdl

【讨论】:

  • 这可能有效,但我已经通过更改为 IntPtr 来修复它。不过谢谢
  • 当然你可以那样做,但那样做的代码更多。无论如何,这个答案解释了这个问题,以防你想理解它。
猜你喜欢
  • 1970-01-01
  • 2011-06-13
  • 2014-08-18
  • 2017-08-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-05-23
  • 1970-01-01
相关资源
最近更新 更多