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

2023-11-29

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

问题是char在C#中是一个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()转换为字符串。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

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

随机推荐