简体   繁体   English

试图将uint8_t *从C#传递到C ++的奇怪问题

[英]Strange Issues Trying to Pass uint8_t* from C# to C++

I am having major issues working with a third-party API from C#. 我在使用C#的第三方API时遇到重大问题。 I do not have the full source code for this API, nor do I know how the DLL was compiled. 我没有此API的完整源代码,也不知道DLL是如何编译的。 I have been trying for many, many hours to figure this out to no avail. 我已经尝试了许多小时,以解决这个问题。

As far as I can tell, the function in question is defined in C++ as such: 据我所知,有问题的函数在C ++中的定义如下:

    extern "C" uint32_t __stdcall GetQHYCCDSingleFrame(qhyccd_handle *handle,
 uint32_t *w, uint32_t *h, uint32_t *bpp, uint32_t *channels, uint8_t *imgdata);

The trouble-object in question is uint8_t *imgdata . 有问题的故障对象是uint8_t *imgdata It is intended to be an array of 8-bit integers, passed by reference to the function. 它打算是一个8位整数数组,通过引用传递给该函数。 In C++, I declare the object as such: 在C ++中,我这样声明该对象:

ImgData = (unsigned char *)malloc(length);
memset(ImgData,0,length);

before passing it to the above function. 在将其传递给上述功能之前。

In C#, I have tried a few different methods of passing the imgdata object correctly, but all result in similar issues. 在C#中,我尝试了几种正确传递imgdata对象的方法,但是所有方法都会导致类似的问题。 For example, I have declared a byte array in C# as: byte[] ImgData = new byte[length] . 例如,我在C#中将字节数组声明为: byte[] ImgData = new byte[length] The GetQHYCCDSingleFrame function is imported into C# using the following declaration: 使用以下声明将GetQHYCCDSingleFrame函数导入C#:

[DllImport("qhyccd.dll", EntryPoint = "GetQHYCCDSingleFrame")]
        public static extern UInt32 GetQHYCCDSingleFrame(IntPtr handle, ref UInt32 w, ref UInt32 h, ref UInt32 bpp, ref UInt32 channels, byte[] rawArray);

I can call the function properly without errors, but I run into issues when trying to use the ImgData array in C#. 我可以正确调用该函数而不会出现错误,但是在尝试在C#中使用ImgData数组时遇到了问题。 In particular, say that I would like to print each element in the array to the console using the following code snippet: 特别是,我想使用以下代码片段将数组中的每个元素打印到控制台:

for (int i = 0; i < length; i++)
{
    Console.WriteLine(Convert.ToString(ImgData[i]));  
}

This appears to run until about the 84,000th element, at which point a pop-up occurs telling me that "Application has stopped working", with no other error information. 这似乎一直运行到第84,000个元素为止,这时会出现一个弹出窗口,告诉我“应用程序已停止工作”,没有其他错误信息。 I can access that element just fine, but if I want to write each element to a .CSV file, looping will always crash my program with no error information. 我可以很好地访问该元素,但是如果我想将每个元素写入.CSV文件,则循环将始终使程序崩溃,并且没有错误信息。 To make things even stranger the following code snippet will work: 为了使事情变得更加陌生,以下代码片段将起作用:

byte safeByte;
for (int i = 0; i < length; i++)
{
   safeByte = rawArray[i];

}

which indicates to me that it's not necessarily a memory-access issue. 这向我表明这不一定是内存访问问题。 And, finally, to make things even more confusing, this code snippet will crash with the same "Application has stopped working" popup: 最后,为了使事情更加混乱,此代码段将与相同的“应用程序已停止工作”弹出窗口崩溃:

byte safeByte;
byte[] newArray = new byte[length];
for (int i = 0; i < length; i++)
{
     safeByte = rawArray[i];
}

except that it will crash while declaring the newArray object, before even entering the loop. 除了在进入循环之前,在声明newArray对象时它将崩溃。

I have tried many solutions from stackoverflow questions similar to mine, but nothing has worked, and I will always get the same "Application has stopped working" popup. 我已经从类似于我的stackoverflow问题中尝试了许多解决方案,但是没有任何效果,并且我将始终得到相同的“应用程序已停止工作”弹出窗口。 I really just need to save this data somehow to a text file in its integer form. 我真的只需要将数据以某种整数形式保存到文本文件中。

Without access to the library itself, it's hard to provide direct help. 如果无法访问库本身,则很难提供直接帮助。 However, interop problems can often be resolved by creating a shim, then contracting the shim's code into non-existence once the shim is working. 但是,互操作性问题通常可以通过以下方式解决:创建垫片,然后在垫片工作后将垫片的代码压缩为不存在。 An added benefit to this approach is that it splits the problem into more manageable chunks, and makes it easier to ask for focused help if stuck. 这种方法的另一个好处是,它可以将问题分成更易于管理的部分,并且如果遇到困难,可以更轻松地寻求重点帮助。

How to solve C#/C++ interop problems via shimming: 如何通过填充解决C#/ C ++互操作问题:

  1. Write a C++ application which can call into the library. 编写一个可以调用该库的C ++应用程序。 Ideally, this is just a matter of compiling a code sample from the vendor. 理想情况下,这仅是编译供应商的代码示例的问题。
  2. Write a trivial C++ library which you can call from C#. 编写一个普通的C ++库,您可以从C#中调用它。 This should just be a matter of compiling a code sample from MSDN or elsewhere. 这应该只是从MSDN或其他地方编译代码示例的问题。
  3. Iteratively modify the signature of the C++ and C# code from step 2 until it is identical to the signature used in step 1. If you get stuck on any of the complex parameters, split them into primitives and pass them individually. 从第2步开始迭代地修改C ++和C#代码的签名,直到与第1步中使用的签名相同为止。如果卡在任何复杂参数上,请将它们拆分为基元并分别传递它们。
    • If you split your parameters into basic enough components, you'll probably be able to find working code samples. 如果将参数分解为足够的基本组件,则可能可以找到有效的代码示例。
    • If you get stuck on a specific parameter, write both a broken version (using the parameter you're stuck on) and a working version (using a parameter you got to work in step 2). 如果您卡在特定的参数上,则写一个残破的版本(使用您所卡住的参数)和一个有效的版本(使用在步骤2中必须使用的参数)。 Then, you can post a question on SO like, 然后,您可以在SO上发布问题,例如,

      The above code works, but when I change the parameter from classA to classB, line 5 causes a crash with the error message "error: foo". 上面的代码有效,但是当我将参数从classA更改为classB时,第5行导致崩溃,并显示错误消息“错误:foo”。 I thought this change was OK because of ZZZ. 由于ZZZ,我认为此更改可以。 How can I add a classB parameter without this crash? 如何在没有崩溃的情况下添加classB参数?

  4. Recompile your application in step 1 as a library. 将步骤1中的应用程序重新编译为库。 Modify the code in step 3 to call this library. 在第3步中修改代码以调用此库。
  5. (Optional) Inline the code from steps 1 and 3 (ie, get rid of the shim). (可选)内联第1步和第3步中的代码(即摆脱垫片)。 If this step fails, you'll probably be stuck on a specific parameter, which again may be suitable to rework into a stackoverflow question. 如果此步骤失败,则您可能会停留在特定的参数上,这又可能适合重新处理stackoverflow问题。
  6. (Optional) Recombine any parameters that were split during step 3. (可选)重新组合在步骤3中拆分的所有参数。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM