在带有参数的函数上使用PInvoke时发生AccessViolationException

本文关键字:PInvoke AccessViolationException 参数 函数 | 更新日期: 2023-09-27 18:00:29

我当前正在使用PInvoke从C#中的C++调用一些非托管函数;特别是PhysX 3.3.3。我对PInvoke还比较陌生,所以我从一些简单的方法开始。我可以很容易地调用不带参数的函数,但调用任何带参数的都有困难。

从简单的开始,我使用了一个传递布尔值的函数,发现布尔值是不可blitable的类型,所以必须封送它们。但是,将布尔封送处理添加到PInvoke签名仍然不起作用。

[DllImport("PhysX3CommonCHECKED_x64.dll", CallingConvention = CallingConvention.Cdecl,
           EntryPoint = "?getReportAllocationNames@Foundation@shdfnd@physx@@UEBA_NXZ")]
public static extern bool GetAllocationNames();
[DllImport("PhysX3CommonCHECKED_x64.dll", CallingConvention = CallingConvention.Cdecl,
           EntryPoint = "?setReportAllocationNames@Foundation@shdfnd@physx@@UEAAX_N@Z")]
public static extern void SetAllocationNames([MarshalAs(UnmanagedType.U1)]bool name);

当我调用SetAllocationNames(true)时,我会得到AccessViolationException。我也尝试过为UnmanagedType枚举使用其他成员名称(例如U1、Bool),但没有成功。

我在调用函数之前加载DLL,使用正确的损坏名称作为入口点,并调用与该函数相关的所有参数(在这种情况下只有一个)。我还缺少什么吗?

在带有参数的函数上使用PInvoke时发生AccessViolationException

不幸的是,如果用不同的编译器编译C++库(甚至更糟的是,同一编译器的不同版本),但单独使用PInvoke,则基本上不可能与其他C++应用程序共享C++库。

其次,你甚至还没有接近解决这个问题。C++对方法(属于类的函数)的调用约定(在x86中)是this调用,这意味着this(方法被调用的类)是通过ecxrcx寄存器传递的。cdecl没有通过一个。其次,你甚至没有定义合适的类。。。

您应该做的是编写一个C++包装器

编写函数,而不是方法(即不绑定到任何类或结构),它们可以执行您需要执行的任何操作,并确保您知道它们的调用约定(使其成为常规的,如cdeclfastcall)。通过这种方式,您可以编写C/C++代码来为您完成工作,并使用PInvoke编写C#

好吧,我想我现在明白了。经过进一步的研究,似乎继承的功能对PInvoke来说是有问题的。许多来源建议将C++代码扁平化为C风格的接口。我将不得不使用C++/CLI项目。谢谢