如何在c#中存储从C ++函数返回的uint8_t *变量?

我从我的C#程序中调用了一个C ++ DLL。 DLL由几个函数组成,除了这个函数之外,我能够调用其中的大多数函数。

C ++函数如下所示:

__declspec(dllexport) uint8_t* myHash(const char *filename) { uint8_t *hash = (unsigned char*)malloc(72*sizeof(uint8_t)); //some processing on hash return hash; } 

从上面的代码中可以看出,散列函数存储了一个字符数组。 我想在我的C#程序中收到值,但我无法做到。

我的C#代码如下所示:

  [DllImport("myHash.dll", CharSet = CharSet.Ansi)] public static extern IntPtr myHash(string filename); IntPtr ptr = myHash(fileA); char[] result = new char[72]; Marshal.Copy(ptr, result, 0, 72); 

问题是C#中的char是一个16位字符元素。 您的C ++代码返回一个8位uint8_t值的数组。 您应该切换到使用字节数组。

 [DllImport("myHash.dll", CallingConvention=CallingConvention.Cdecl, CharSet = CharSet.Ansi)] public static extern IntPtr myHash(string filename); .... IntPtr ptr = myHash(fileA); byte[] result = new byte[72]; Marshal.Copy(ptr, result, 0, 72); 

我指定了一个调用约定,因为正如所写,你的函数是__cdecl 。 也许你在转录问题时省略了一些内容,但上面的声明与问题中的非托管代码相匹配。

这个函数设计得更好,允许调用者分配缓冲区。 这避免了您必须从C ++代码导出deallocator。 我会像这样编写C ++:

 __declspec(dllexport) int myHash(const char *filename, uint8_t* hash) { // calculate hash and copy to the provided buffer return 0; // return value is an error code } 

和相应的C#代码:

 [DllImport("myHash.dll", CallingConvention=CallingConvention.Cdecl, CharSet = CharSet.Ansi)] public static extern int myHash(string filename, byte[] hash); .... byte[] hash = new byte[72]; int retval = myHash(fileA, hash); 

这个函数在其接口中硬编码,缓冲区长度为72.这可能是合理的,但是传递缓冲区的长度也是有意义的,这样非托管代码可以防止缓冲区溢出。

请注意,尽管您将此函数的输出称为字符数组,但使用uint8_t*使其看起来更像是一个字节数组。 如果它确实是一个字符数组,那么您可以使用Encoding.GetString()转换为字符串。