编程语言
首页 > 编程语言> > 如何在C#中存储从C函数返回的uint8_t *变量?

如何在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代码导出解分配器.我会这样写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()转换为字符串.

标签:c,pinvoke,c-2
来源: https://codeday.me/bug/20191013/1909299.html