我有一个函数,由于保护和抽象,我无法改变,它被声明为:
GetDeviceLongInfo(int, int, ref int);
其中要传递的“ref int”参数据说可以返回6400字节的信息。
我的问题是,如果我唯一的选择是给函数Int32
,我怎样才能在变量中获取这些信息?我可以为Int32
分配更多内存吗?这有可能以某种方式实现吗?
编辑: 我可以告诉你,该函数使用ref int来转储其中的值,int size(信息的大小)不固定,取决于在第二个参数中选择的选项。我甚至无法查看该函数以了解它如何使用该参考。
答案 0 :(得分:1)
您可以分配int[]
并将其传递给该函数。这是一个黑客,但我不明白为什么它不安全。
var array = new int[6400 / sizeof(int)];
GetDevice(..., ref array[0]);
在调用期间,数组由CLR固定。
注意,ref
是一个所谓的CLR托管指针。它通过将其作为指针传递并固定它指向的对象进行编组。 int[]
将以几乎相同的方式传递(传递指向第一个元素的指针)。
答案 1 :(得分:0)
我可以为Int32分配更多内存吗?否
这有可能以某种方式实现吗?更改签名或使用int作为对数据的引用都是选项
答案 2 :(得分:0)
您正在尝试将数组(对数据的本机指针)编组为整数。 C#对此没有任何问题,但处理它是另一回事。另请注意,根据您的体系结构,您将拥有不同的指针大小,这意味着使用32位int不是最佳选择。
另请参阅:http://msdn.microsoft.com/en-us/library/z6cfh6e6(v=vs.110).aspx
我不记得我头脑中的细节,但基本上你想使用MarshalAs告诉.NET它是一个指向数组的指针。 IIRC就是这样的(1600 = 6400/4):
void GetDeviceLongInfo(int, int, [MarshalAs(UnmanagedType.LPArray, SizeConst=1600)] int[] ar );
<强>更新强>
我注意到关于它如何工作的问题,所以这里是......这个签名将如何工作:C中的签名可能是(long, long, long*)
,这意味着第三个参数应该是指向int的指针。底层缓冲区将通过GetDeviceLongInfo
或类似的东西填充strncpy
。可能出错的事情是传递一个太小的缓冲区(在VS中调试模式下运行它),使用错误的处理器架构,错误地传递整数而不是指针(你可以试试)将AllocHGlobal的地址转换为int并查看它是否有效 - 这意味着你必须在x86上运行)并且基本上还有很多其他的东西: - )
显然你无法改变签名的任何内容。您基本上尝试做的是分配缓冲区,将其转换为int*
然后处理它。由于usr
的方法不起作用,我尝试Marshal.AllocHGlobal
创建缓冲区,然后将其传递给函数(如果需要,使用不安全的代码)。