如何存储uint8_t有*变量在C#中的C ++函数返回? [英] How to store a uint8_t* variable returned from a C++ function in c#?

查看:300
本文介绍了如何存储uint8_t有*变量在C#中的C ++函数返回?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我打电话是从我的C#程序中的C ++ DLL。该DLL包含多种功能,我能叫他们大多只是这一个。



C ++函数就像如下:

  __declspec(dllexport)的uint8_t有* myHash(为const char *文件名)
{
uint8_t有*哈希=(无符号字符*)malloc的(72 * sizeof的(uint8_t有));
//散列
返回哈希一些处理;
}



如在上述代码中可以看出,散列函数存储的字符阵列。我希望收到我的C#程序中的值,但我不能做到这一点。



我的C#代码就像如下:

 函数[DllImport( myHash.dll,字符集= CharSet.Ansi)] 
公共静态外部的IntPtr myHash(字符串文件名);

IntPtr的PTR = myHash(的fileA);
的char []结果=新的char [72];
Marshal.Copy(PTR,结果,0,72);


解决方案

的问题是,字符在C#是一个16位字符元素。你的C ++代码返回8位的数组uint8_t有值。你应该切换到使用一个字节数组来代替。

 函数[DllImport(myHash.dll,CallingConvention = CallingConvention.Cdecl,
字符集= CharSet.Ansi)]
公共静态外部的IntPtr myHash(字符串文件名);
....
IntPtr的PTR = myHash(的fileA);
的byte []结果=新的字节[72];
Marshal.Copy(PTR,结果,0,72);



我指定的调用约定,因为,书面,你的函数是 __ CDECL 。也许你忽略了问题的转录东西,但声明上述问题的非托管代码相匹配。



本功能将更好地设计,让呼叫者分配缓冲区。那您就无需一个释放器从C ++代码出口。我会写的C ++这样的:

  __ declspec(dllexport)的INT myHash(为const char *文件名,uint8_t有*哈希)
{
//计算哈希值,并复制到提供的缓冲区
返回0; //返回值是一个错误代码
}

和相应的C#代码:

 函数[DllImport(myHash.dll,CallingConvention = CallingConvention.Cdecl,
字符集= CharSet.Ansi)
公共静态外部INT myHash(字符串的文件名,字节[]哈希值);
....
字节[] =哈希新的字节[72];
INT RETVAL = myHash(的fileA,哈希值);

这个功能在其接口缓冲区的长度是72。这可能是合理的硬编码,但它可能是有意义的传递缓冲区的长度也使非托管代码可以抵御缓冲区溢出。



请注意,虽然你是指这个函数的输出作为一个字符数组,uint8_t有* 使用的使它看起来更可能是一个字节数组。如果这真的是一个字符数组,那么你可以使用 Encoding.GetString()来转换为字符串。


I am calling a C++ dll from my C# program. The DLL consists of several functions and I am able to call most of them except this one.

The C++ function is like as below:

 __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.

My C# code is like as below:

 [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. Your C++ code returns an array of 8 bit uint8_t values. 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. 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. I'd write the C++ like this:

__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:

[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.

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. If it really is a character array, then you can use Encoding.GetString() to convert into a string.

这篇关于如何存储uint8_t有*变量在C#中的C ++函数返回?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆