我正在将一些托管的 C++ 转换为 c# 代码,这需要我从其他 c++ 项目的相当多的 dll 中 p/invoke 函数。当您 p/invoke 这些函数时,您可以指定与 C++ 函数期望的参数类型不同。这是如何运行的?因为这不会给出编译器错误。例如:当函数需要一个 int 参数时,我的 C# pinvoked 函数提供了一个 datetime 参数。
2 回答
它不会给您编译器错误,因为它不会在编译时发生。编组器在编译时并没有关于本机方法和类型的任何信息(除了 pinvoke 签名),因此无法为您提供帮助。
MSDN状态下的大多数 pinvoke 帮助页面:
P/Invoke 提供很少的编译时错误报告,不是类型安全的
如果您想更细致入微地了解 p/invoke,那么您可以找到大量文章和博客文章。以下是我推荐你阅读的一些内容:
您可以在 [DllImport] 声明中撒谎,pinvoke marshaller 几乎无法检测到您的声明不匹配。它所知道的只是有一个具有特定名称的 DLL 文件,它导出具有特定名称的函数。它不能告诉函数接受什么参数,也不知道它返回什么。这需要更好的函数元数据,即 COM 类型库或 .NET 程序集元数据可以提供的那种。普通 DLL 不存在此类元数据,因此它必须假定您的声明是准确的。
这实际上通常非常有用,它允许您将 void* 映射到 byte[] 或 IntPtr 映射到引用类型引用或 ref 传递的值类型。您可以编写相同函数的重载。
故意弄错了,比如希望 DateTime 将映射到int,如果幸运的话,可以通过硬崩溃来诊断。像 AccessViolationException 或 PInvokeStackImbalance。但是,不能保证这种运气,它很可能会产生垃圾。