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

Posted

技术标签:

【中文标题】如何在 C# 中存储从 C++ 函数返回的 uint8_t* 变量?【英文标题】:How to store a uint8_t* variable returned from a C++ function in c#? 【发布时间】:2014-02-03 11:27:17 【问题描述】:

我正在从我的 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;
    

从上面的代码可以看出,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);

【问题讨论】:

【参考方案1】:

问题是 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++ 代码中导出释放器。我会这样写 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()转换成字符串。

【讨论】:

我尝试了您提供的第一个使用 byte[] 的解决方案。它给了我我怀疑不正确的价值观。 我的答案中的第一段代码与问题中的代码相匹配。如果出现问题,那肯定是问题中的代码与您正在运行的代码不同,或者您的非托管代码的行为方式与您期望的不同。 我重复一遍。我的答案中的代码与问题中的代码相匹配。也许您可能想解释为什么您认为 250、162、234 等值不是在字节数组散列中找到的合理值。一个字节的值在 0..255 范围内。你提到的价值观似乎很符合要求。

以上是关于如何在 C# 中存储从 C++ 函数返回的 uint8_t* 变量?的主要内容,如果未能解决你的问题,请参考以下文章

嵌入式单声道:将数组从 C# DLL 返回/复制到 C++

如何将结构数组从 c++ 传递到 c#?

C#从返回char指针的c++函数中获取字符串/字符值

c# - 如何调用分配输出缓冲区以在c#中返回数据的非托管c++函数?

如何将对象列表从 C++ 传递到 C#?

为啥 C++ 从 C# 中为返回自定义结构的函数获取错误的参数值