Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/158.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# PInvoke:返回的双打数组有问题吗? < >我使用 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); [DllImport("VirtualHandBridge.dll")] static public extern IntPtr Poll(IntPtr hand);_C#_C++_Types_Double_Pinvoke - Fatal编程技术网

C# PInvoke:返回的双打数组有问题吗? < >我使用 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); [DllImport("VirtualHandBridge.dll")] static public extern IntPtr Poll(IntPtr hand);

C# PInvoke:返回的双打数组有问题吗? < >我使用 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); [DllImport("VirtualHandBridge.dll")] static public extern IntPtr Poll(IntPtr hand);,c#,c++,types,double,pinvoke,C#,C++,Types,Double,Pinvoke,Poll()的签名如下所示: IntPtr data = Poll(this.vhtHand); double[] arr = new double[NR_FINGERS /* = 5 */ * NR_JOINTS /* = 3*/]; Marshal.Copy(data, arr, 0, arr.Length); [DllImport("VirtualHandBridge.dll")] static public extern IntPtr Poll(IntPtr hand); C函数轮询

Poll()
的签名如下所示:

IntPtr data = Poll(this.vhtHand);
double[] arr = new double[NR_FINGERS /* = 5 */ * NR_JOINTS /* = 3*/];
Marshal.Copy(data, arr, 0, arr.Length);
[DllImport("VirtualHandBridge.dll")]
static public extern IntPtr Poll(IntPtr hand);
C函数
轮询
的签名:

extern "C" __declspec(dllexport) double* Poll(CyberHand::Hand* hand)
除非我有一个巨大的脑功能衰竭(不可否认,这对我来说相当普遍),否则在我看来它应该是有效的

但是,我得到的双值是完全不正确的,我认为这是因为内存使用不正确。我已经查过了,我认为C和C++中的双打大小相同,但也许这里还有其他问题。有一件事让我恼火,那就是,
Marshal.Copy
从未被告知它应该使用哪种类型的数据,但我读到它应该以这种方式使用


有什么线索吗?如果需要,我可以发布正确的结果和返回的结果。

只要正确声明p/Invoke,您甚至不需要这样封送数据

如果您的
CyberHand::Hand*
实际上是指向double的指针,那么您应该将p/Invoke声明为

[DllImport("VirtualHandBridge.dll")]
static public extern IntPtr Poll(double[] data);
然后用你的双倍数组来调用它

如果它不是一系列的双打,那么你肯定不能做你正在做的事情

另外,“C”函数如何知道数组的大小?是固定尺寸的吗

IntPtr返回值将是一个问题。
double*
指向什么?数组还是单个项

您会发现,为正在调用的函数编写一个更简单、更友好的“C”包装器并调用包装器函数本身更容易(如果可以的话)。当然,只有在可以更改“C”DLL的源代码时,才能这样做。但是如果不知道你的函数是做什么的,我不能给你具体的建议

[编辑]

好的,如果被传回的内存没有被弄乱(例如释放),理论上你的代码应该可以工作。如果它不起作用,那么我怀疑类似的事情正在发生。您最好编写一个包装器“C”函数,填充由C#分配并传递给函数的数组,而不是返回指向某个内部内存的指针


顺便说一句:我不喜欢在不传递内存块大小的情况下传递指向内存块的指针的代码。似乎有点容易发生不愉快的事情。

您缺少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返回值报告状态代码。与报告错误代码的负值一样,返回实际复制到缓冲区的元素数的正值。

CyberHand::Hand*不是指向double的指针,而是指向C函数将从中提取数据的对象的指针。函数的返回值是双指针。返回指针的内存是如何分配的?谁负责释放它?你怎么知道它有多大?Poll的代码看起来像:
hand->updateData();double*rv=手->关节();返回rv。释放内存是我以后要解决的问题;它当前没有被释放,所以应该保留在那里。@ArnoSluismans C代码如何实例化CyberHand::Hand对象?在C语言中实例化一个非托管C++类是困难和不便的。如果你还没有处理好这件事,那么要让它发挥作用还有很长的路要走。这里的自然解决方案是将手转为COM类,这是将非托管C++类暴露给.NET的方法。@ USE1610015,我不在C语言中实例化它。我只保存一个指向该对象的指针,它存储为<代码> ItpTrt/COD>。然后,对于每一个我需要调用的方法(我故意把这个方法的数量尽可能地低),我称C++方法,它使用<代码> CythPoo::然后,该方法将在
CyberHand::Hand
中调用正确的方法。遗憾的是,这意味着我需要为每个必需的方法调用构建这样一个桥接方法。它很笨重,但我读到这是最好的方法。删除了我以前的评论,因为我没有思考清楚。非常感谢,这段代码非常有效,您的建议非常有用。