【问题标题】:Return type mismatch of Visual C++Visual C++ 的返回类型不匹配
【发布时间】:2012-12-08 11:23:50
【问题描述】:

我在 Visual C++ 中有以下返回类型:

extern "C" __declspec(dllexport) unsigned char* _cdecl 
                                          getname(LPCTSTR Track1, int len)

我已经编写了以下代码以在 C# 中获取 unsigned char* 的正确值:

[DllImport(_dllLocation, CallingConvention = CallingConvention.Cdecl)]
 public static extern byte[] getname(string track1, int len);

我使用以下代码从另一个 .cs 文件中调用了上述方法:

string track = "hello12345"; 
byte[] name = UnsafeNativeMethods.getname(track, 160);

请告诉我在这里做错了什么,还请检查参数数据类型,即LPCTSTRstring

unsigned char* 是否等同于 byte[]。如果是这样,那么为什么我在 C# 文件中得到错误的值,而在 C++ 中它是正确的。

编辑:

在通过 cmets 提出一些建议后,我已将 byte name 更改为 byte[] name,但它显示以下异常:

A first chance exception of type 'System.Runtime.InteropServices.MarshalDirectiveException' occurred in DecryptionWS.dll
A first chance exception of type 'System.Runtime.InteropServices.MarshalDirectiveException' occurred in DecryptionWS.dll
A first chance exception of type 'System.Runtime.InteropServices.MarshalDirectiveException' occurred in   System.ServiceModel.dll
A first chance exception of type 'System.Runtime.InteropServices.MarshalDirectiveException' occurred in System.ServiceModel.dll

【问题讨论】:

  • 您的getname extern 方法返回一个字节,但您像byte[] 一样使用它。是字节还是字节[]?
  • 我的错,现在我编辑了它
  • 我也试过了:byte[] name = UnsafeNativeMethods.getname(track, 160); Console.Writeline (name); 但它会停止程序并抛出System.InvalidOperationException' occurred in System.ServiceModel.Web.dll
  • Console.WriteLine(name) 只会打印System.Byte[]。你期待什么价值?如果您需要一个字符串,则需要使用System.Text.Encoding.UTF8.GetString(name)(或您使用的任何编码格式)。
  • @keyboardP 请看代码编辑部分

标签: c# visual-studio-2010 visual-c++ types bytearray


【解决方案1】:

unsigned char*byte[] 并不完全等价。 unsigned char* 是指向字节的指针,而byte[] 是具有已知长度的字节数组。 unsigned char* 的长度未知。 .Net 编组器无法直接从 unsigned char* 编组到 byte[],因为它不知道缓冲区的长度。

所以你必须手动编组返回值:

  1. 更改您的 p/Invoke 函数定义以返回 IntPtr(即通用指针值)`
  2. 使用Marhsal.CopyIntPtr 复制到一个字节数组。

示例:

[DllImport(_dllLocation, CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr getname(string track1, int len);


string track = "hello12345"; 
IntPtr namePtr = UnsafeNativeMethods.getname(track, 160);
Byte[] name = new Byte[/* some size here - it is not clear how*/];
Marshal.Copy(namePtr, name, 0, name.Length);

【讨论】:

  • 我输入了尺寸 160 ,然后我在输出中打印了 name ,它显示了我:System.Byte[]。这是什么意思?
  • .ToString() 在任何数组类型上返回类型的名称,在本例中为 System.Byte[]。你对字节数组的内容有什么期望。一个字符串?
  • 最后我想把这个name 变量转换成Hex 字符串。但我无法从name 变量中获取数据。我该怎么做?
猜你喜欢
  • 2015-10-30
  • 2021-03-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多