【发布时间】: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 有效!谢谢!