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

标签 c# c++ pinvoke

我正在从我的 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++ 代码导出解除分配器。我会这样写 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);

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

请注意,虽然您将此函数的输出称为字符数组,但 uint8_t* 的使用使其看起来更像是字节数组。如果真的是字符数组,那么可以使用Encoding.GetString()转成字符串。

关于c# - 如何在 C# 中存储从 C++ 函数返回的 uint8_t* 变量?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21526149/

相关文章:

c# - 将 C# 字典编码到 C++(非托管)

C# 应用程序调用 C++ 方法,错误 : PInvoke: Cannot return variants

c# - 如何使用 PInvoke 传递图像

c# - 如何从 SOS 的 jitted 输出中获取托管函数名称?

c# - 如何减去日期时间以按照我需要的格式给出结果?

c++ - C/C++ 优化编译器因使用模板而损坏

c++ - 前向声明与包含在 Google C++ 风格指南中

c# - C#获取磁盘簇大小--出现 'GetDiskFreeSpace'错误

c# - OpenXML如何检查工作表中的一行是否为空

c# - Entity Framework 试图插入错误的表?