Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# P/Invoke传递结构的时间比本机代码预期的要长_C#_.net_Pinvoke - Fatal编程技术网

C# P/Invoke传递结构的时间比本机代码预期的要长

C# P/Invoke传递结构的时间比本机代码预期的要长,c#,.net,pinvoke,C#,.net,Pinvoke,如果我有一个本机代码,它需要一个包含两个字段的结构: [DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl)] public static extern int my_method(ref MyStruct myStruct); // this is what native code expects public struct MyStruct { IntPtr First; IntPtr Sec

如果我有一个本机代码,它需要一个包含两个字段的结构:

[DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl)]
public static extern int my_method(ref MyStruct myStruct);

// this is what native code expects
public struct MyStruct {
    IntPtr First;
    IntPtr Second;
}
但是,相反,我将另一个结构传递给它,它会工作吗?是设计还是意外

[DllImport(LibraryName, CallingConvention = CallingConvention.Cdecl)]
public static extern int my_method(ref MyLongerStruct myLongerStruct);

// this is what I want to pass to it
public struct MyLongerStruct {
    IntPtr First;
    IntPtr Second;
    object ObjectPointer;
}

添加到C端结构末尾的对象引用是否会影响p/Invoke调用?

我不应该工作。更重要的是,您需要添加StructLayoutAttribute并将其正确设置为该结构,正如它所解释的

我想,结果应该是这样的:

[StructLayout(LayoutKind.Sequential)]
public struct MyStruct {
    IntPtr First;
    IntPtr Second;
}

如果结构上的总差异是在末尾添加字段,并且您使用
StructLayout
阻止编译器优化结构的内存布局(正如Alex Butenko所建议的),那么除了轻微的速度影响之外,不太可能有任何负面的副作用

当您通过p/Invoke(使用
DllImport
属性)将托管的
struct
传递给外部函数时,会有一个封送阶段,将您的结构转换为与目标兼容的格式。对于
ref
out
参数,当调用的函数返回时,将临时值转换回,并将值复制回
struct
实例。所有这些都被抽象掉了,尽管可以使用正确的属性调整每个成员的封送处理方式

这就是.NET framework在p/Invoke中处理字符串的方式。因为它不能只发送一个
字符串
实例指针到一个需要
字符*
的API函数(这两个函数完全不同),所以必须进行一些转换

有趣的是,封送处理代码除了在C#end告诉它什么之外,对目标的期望一无所知,因此,如果你发送的是结构的扩展版本,它将完成全部工作。在另一端,本机代码将获得一个指向内存块的指针,该内存块包含它所期望的信息,并且它无法判断在结构结束后还有更多信息


除此之外,没问题。。。只要您是通过引用而不是通过值传递。按值传递结构应该会在你的大脑中出现红色的停止标志。不要这样做,这是邪恶的。

为什么不应该这样做?(假定布局是正确的,因为它位于P/Invoke上下文中)。如果
object
IntPtr
呢?结构应该有正确顺序的确切成员数。StructLayout是为了确保顺序,因为编译器可以对它们重新排序,并以错误的顺序将其传递给extern函数。谢谢!这也是我的想法。我想知道字段
对象ObjectPointer
的封送是否总是成功,还是取决于实际的对象类型?当然,它会影响pinvoke调用,封送器将不得不做更多的工作。在这种情况下需要做更多的工作,因为它是一个对象,根据您传递的值,很容易失败。本机代码完全没有注意到它,因为它不读取成员。让它来做这件事或者冒险是毫无意义的。谢谢!我想将
MyStruct
作为
MyLongerStruct
的第一个字段,并且只传递
MyStruct
是一个完美的解决方案?如果该结构作为成员嵌入到另一个结构中,那么添加字段显然是一个错误。由于结构成员大小错误,因此会影响所有后续成员的偏移量。这个问题非常需要一个“我到底为什么要这样做”的解释。这个问题是为了更深入地理解编组是如何工作的。我打算将_unpinner字段从添加到,以便在DirectBuffer的生命周期内固定缓冲区。但后来完全重新设计了这两个结构,以避免奇怪的事情。