为什么调用 DLL 中的函数时需要“ref”关键字?

我试图弄清楚为什么我需要使 DLLImport 函数的参数为“ref int XXX”,而不仅仅是“int XXX”。对于后者,这会导致“尝试读取或写入受保护的内存。这通常表明其他内存已损坏。” 问题......但是当我将“ref”添加到参数中......它工作得很好。例如:

    [DllImport("someDLL.dll", CallingConvention = CallingConvention.StdCall)]
        public static extern int SomeDLL_GetDevices(ref int devices);

^ 以上作品

    [DllImport("someDLL.dll", CallingConvention = CallingConvention.StdCall)]
        public static extern int SomeDLL_GetDevices(int devices);

^ 以上崩溃和烧伤

我不是从 C# 及其编组方面进行 C++ 调用的导出,因此如果有人可以解释为什么一个有效而另一个无效,我将不胜感激。


胡子哥哥
浏览 77回答 1
1回答

阿晨1998

上面ref int说“被调用者期望一个指向 32 位整数的指针,而编组器期望它是一个托管指针”。指向整数的托管指针和整数是两个完全不同的东西。一种是指针大小的——通常是 64 位——另一种肯定是 32 位。一种是值,一种是描述从哪里获取包含值的变量。它们不可互换,您需要正确使用。如果您不清楚编组层为实现这一点而使用的约定,请在编写更多编组代码之前弄清楚它。 您正在与一个不具有 C# 提供的类型安全或内存安全的系统进行交互,因此您需要确保保留运行时的不变量。通常,运行时会确保维护运行时不变量,但您正在描述如何与运行时之外的代码进行交互,因此请确保它是正确的。尝试一些东西直到它起作用并不是一个好技巧。如果继续这样做,您可能会引入崩溃、内存泄漏和更微妙的错误(即安全漏洞)。阅读文档、书籍或视频,或者让同事向您解释,以便您了解其工作原理。然后您将能够充满信心地编写 p/invoke 代码,而不是猜测和希望。
打开App,查看更多内容
随时随地看视频慕课网APP