从托管代码向非托管代码传递参数

3

我需要使用一个库中的方法,它在头文件中具有以下签名:

NKREMOTELIB_API int __stdcall GetEvfFrame(
    const unsigned char*& buffer,
    size_t& size,
    NKRemoteEvfDisplayInfo& displayInfo);

我将使用以下c#代码进行调用:

我正在使用以下c#代码进行调用:

[DllImport("NKRemoteLib.dll")]
public static extern int GetEvfFrame(out IntPtr buffer, out IntPtr size, out NKRemoteEvfDisplayInfo displayInfo);

private void Test() {
    IntPtr size = new IntPtr();
    IntPtr buffer = new IntPtr();
    NKRemoteEvfDisplayInfo displayInfo;
    int res = GetEvfFrame(out buffer, out size, out displayInfo);
}

我在c#中定义了一个名为displayInfo的结构体。

我的问题是在头文件中函数签名中的&符号是否有任何意义?为什么使用size_t&而不是size_t或char*& 而不是char*?


为什么使用 size_t& 而不是 size_t?因为它是以这种方式实现的,没有明显的原因这样做。 - Lukasz Madon
谢谢Lukas,我实际上是在问“&”符号的语义意义。 - devprog
3个回答

1

“&”符号表示传递引用语义。换句话说,函数GetEvfFrame将引用一个size_t值,而不是size_t值本身。

您的p/invoke签名应该使用ref而不是out。


使用 ref 和 out 有什么区别? - devprog
ref 表示你可以向函数传递一个值,而该函数可能会修改该值。 out 表示必须由您调用的函数覆盖传递的任何值。 - Kent Boogaart

1

这与C++/C#互操作无关,实际上是关于C++的。

C++有引用的概念。当您通过引用传递对象时,实际上是传递对象本身,而不仅仅是副本。这意味着在被调用者中对对象进行的任何修改都将出现在调用者中。C#具有类似的概念,使用outref关键字。

您可以通过以下方式进行测试:

void f(int i)
{
    i = 5; 
}
void g(int &i)
{
    i = 5;
}

int i = 0, j = 0;
f(i);
g(j);
std::cout << i; // should print 0
std::cout << j; // should print 5

关于为什么会有一个&符号,很可能是因为这些是输出参数:也就是说,调用者希望函数修改这些值。这样做是为了规避类似C语言的“单返回值”限制。

0

符号&(&)代表“引用”。这基本上与您的C# out修饰符相同。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接