PInvoke的:问题与双打的返回数组?(PInvoke: Issue with returned

2019-08-19 10:13发布

我使用PInvoke调用从我的C#程序中的C ++函数。 代码如下所示:

IntPtr data = Poll(this.vhtHand);
double[] arr = new double[NR_FINGERS /* = 5 */ * NR_JOINTS /* = 3*/];
Marshal.Copy(data, arr, 0, arr.Length);

随着Poll()的签名看起来像这样:

[DllImport("VirtualHandBridge.dll")]
static public extern IntPtr Poll(IntPtr hand);

在C-功能Poll的签名:

extern "C" __declspec(dllexport) double* Poll(CyberHand::Hand* hand)

除非我有一个巨大的脑功能衰竭(诚然,相当普遍的对我来说),这看起来对我来说,这应该是工作。

不过,我收到双重价值是完全不正确的,我想这是因为不正确的内存使用量。 我已经看着它,我想在C#和C ++双打的大小是相同的,但也许有一些其他的问题,在这里打球。 这有点让我反感这样的一件事是Marshal.Copy是从来没有告诉它应该期待什么类型的数据,但我读了它应该这样使用。

任何线索,任何人吗? 如果需要,我可以张贴正确的结果,并返回结果。

Answer 1:

这是因为丢失了CallingConvention属性,它是CDECL。

你真的想为有利于更好的函数签名,你有一个非常脆由于内存管理问题,需要手动封送处理,获得正确的尺寸阵列和复制数据的需求的不确定性。 总是青睐来电者通过您的本机代码中填充的缓冲区:

extern "C" __declspec(dllexport)
int __stdcall Poll(CyberHand::Hand* hand, double* buffer, size_t bufferSize)

[DllImport("foo.dll")]
private static extern int Poll(IntPtr hand, double[] buffer, int bufferSize)

使用int返回值来报告的状态码。 像负值来报告错误代码,正值返回元件的数目实际复制到缓冲器中。



Answer 2:

你不应该甚至需要名帅这样的数据,只要你声明P /正确地调用。

如果您CyberHand::Hand*是在现实中的指针,双,那么你应该声明你的P / Invoke为

[DllImport("VirtualHandBridge.dll")]
static public extern IntPtr Poll(double[] data);

然后只需用双打的阵列调用它。

如果它是不是真的双打的数组,那么你一定不能做你在做什么。

另外,请问你的“C”函数知道数组有多大呢? 它是一个固定的大小?

该IntPtr的返回值将是一个问题。 什么是double*指向? 阵列或单个项目?

你会发现,它更容易(如果你能)写为你调用该函数的更简单更友好的“C”的包装,并调用包装函数本身。 你当然只能这样做,如果你可以改变“C” DLL的源代码。 但是,不知道你的功能究竟是干什么的,我不能给你具体的建议。

[编辑]

好吧, 如果被传递回内存不被搞砸与周围(例如释放出来),你的代码应该从理论上工作。 如果它不工作,那么我怀疑这样的事情正在发生。 你一定会更好写的包装“C”功能,在由C#分配和传递给函数,而不是传回一个指向某个内部存储器阵列填充。

顺便说一句:我不喜欢它绕过指针的存储器的块还没有经过该块的大小的代码。 似乎有点容易产生令人讨厌的事情。



文章来源: PInvoke: Issue with returned array of doubles?