简体   繁体   English

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

[英]How to store a uint8_t* variable returned from a C++ function in c#?

I am calling a C++ dll from my C# program. 我正在从C#程序调用C ++ dll。 The DLL consists of several functions and I am able to call most of them except this one. DLL由几个功能组成,除此功能外,我可以调用其中的大多数功能。

The C++ function is like as below: 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;
    }

As can be seen in the above code, the hash function stores a character array. 从上面的代码可以看出,哈希函数存储一个字符数组。 I want to receive the values in my C# program but I am not able to do it. 我想在我的C#程序中接收值,但是我无法做到这一点。

My C# code is like as below: 我的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);

The problem is that char in C# is a 16 bit character element. 问题在于C#中的char是一个16位字符元素。 Your C++ code returns an array of 8 bit uint8_t values. 您的C ++代码返回一个8位uint8_t值的数组。 You should switch to using a byte array instead. 您应该改为使用字节数组。

[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);

I specified a calling convention because, as written, your function is __cdecl . 我指定了调用约定,因为按照您的__cdecl ,您的函数是__cdecl Perhaps you omitted something in the transcribing of the question, but the declaration above matches the unmanaged code in the question. 也许您在问题的转录中省略了一些内容,但是上面的声明与问题中的非托管代码匹配。

This function would be much better designed to allow the caller to allocate the buffer. 此函数将更好地设计为允许调用方分配缓冲区。 That avoids you having to export a deallocator from the C++ code. 这样可以避免您必须从C ++代码中导出解分配器。 I'd write the C++ like this: 我会这样写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
}

And the corresponding C# 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);

This function hard-codes in its interface that the buffer is of length 72. That might be reasonable, but it might make sense to pass the length of the buffer too so that the unmanaged code can defend against buffer overruns. 该函数在其接口中硬编码缓冲区的长度为72。这可能是合理的,但也可以通过缓冲区的长度,以使非托管代码可以防止缓冲区溢出。

Note that although you refer to the output of this function as a character array, the use of uint8_t* makes it seem more likely to be a byte array. 请注意,尽管您将此功能的输出称为字符数组,但使用uint8_t*使其看起来更有可能是字节数组。 If it really is a character array, then you can use Encoding.GetString() to convert into a string. 如果它确实是一个字符数组,则可以使用Encoding.GetString()转换为字符串。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM