无法从C+;中检索正确的字符串+;代码。是否存在处理c#上无符号字符*的泛型类型?

无法从C+;中检索正确的字符串+;代码。是否存在处理c#上无符号字符*的泛型类型?,c#,c++,dllimport,C#,C++,Dllimport,这有点让人困惑,但我会尽力解释的 我试图在C++代码上运行C++ DLL。< /P> 在这个DLL上,我有一个方法,它应该返回一个20个字符的无符号字符*。表示4字节的5个“字”。(sha-1算法的输出) 我在C#项目中使用DLLIMPORT,如下所示: [DllImport("hashLibrary.dll", CharSet = CharSet.Ansi)] static private extern string CallReturnString(IntPtr pHashC

这有点让人困惑,但我会尽力解释的

我试图在C++代码上运行C++ DLL。< /P> 在这个DLL上,我有一个方法,它应该返回一个20个字符的无符号字符*。表示4字节的5个“字”。(sha-1算法的输出)

我在C#项目中使用DLLIMPORT,如下所示:

    [DllImport("hashLibrary.dll", CharSet = CharSet.Ansi)]
    static private extern string CallReturnString(IntPtr pHashClassObject);
这将返回5个单词的字符串

这是我的C++方法,应该给出字符串:

unsigned char* SHA1::Result(/*unsigned *message_digest_array*/)
{
int i;                                  // Counter
int j = 0;
static int s_chString[5];
static unsigned char s_out[20]; // 4 * 5 + 10 de bob
if (Corrupted)
{
    return false;
}

if (!Computed)
{
    PadMessage();
    Computed = true;
}

unsigned int a = 0;
a = H[0];
s_out[0] = (a >> (8*0)) & 0xff;
a = H[0];
s_out[1] = (a >> (8*1)) & 0xff;
a = H[0];
s_out[2] = (a >> (8*2)) & 0xff;
a = H[0];
s_out[3] = (a >> (8*3)) & 0xff;

a = H[1];
s_out[4] = (a >> (8*0)) & 0xff;
s_out[5] = (a >> (8*1)) & 0xff;
s_out[6] = (a >> (8*2)) & 0xff;
s_out[7] = (a >> (8*3)) & 0xff;

a = H[2];
s_out[8] = (a >> (8*0)) & 0xff;
s_out[9] = (a >> (8*1)) & 0xff;
s_out[10] = (a >> (8*2)) & 0xff;
s_out[11] = (a >> (8*3)) & 0xff;

a = H[3];
s_out[12] = (a >> (8*0)) & 0xff;
s_out[13] = (a >> (8*1)) & 0xff;
s_out[14] = (a >> (8*2)) & 0xff;
s_out[15] = (a >> (8*3)) & 0xff;

a = H[4];
s_out[16] = (a >> (8*0)) & 0xff;
s_out[17] = (a >> (8*1)) & 0xff;
s_out[18] = (a >> (8*2)) & 0xff;
s_out[19] = (a >> (8*3)) & 0xff;
s_out[20] = '\0';



return s_out;
}
在这段代码中,我尝试从H中获取所有字节,并将其放入一个将被传递到C代码的字符中

H声明为:
无符号H[5]

它几乎可以工作,但出于某种原因,某些组合会给我疯狂的结果,比如C#上的22个成员的字符串,并且值都是错误的

我认为它与C和C++的一些不同类型的变量有关。强>如果我只能从Car中得到所有字节,就像C++代码中的字节一样,那就太棒了。< /强> < /P> 有人知道怎么做吗

谢谢大家

编辑: 一般的工作流程是:

  • 我的Windows窗体应用程序从C++类创建一个新类:<代码> HasRePAPER hash =新建HASWRAPEPARE();代码>
  • <> Li > Windows窗体应用程序向C++发送种子(这是SHA-1算法类):<代码> hash .sDeNeTe[(ABC));<代码>
  • 我的Windows窗体应用程序要求C++算法的结果:<代码>字符串输出= hash。代码>
  • 在这里,我将把我调用的方法放在列表的顶部:

     public HashWrapper()
        {
            // We have to Create an instance of this class through an exported function
            this.m_pNativeObject = CreateSHA1Class();
        }
    
    public void SendInput(string inp )
        {
            CallInput(this.m_pNativeObject, inp, inp.Length);
        }
    
    public string ReturnString()
        {
    
            string ans = CallReturnString(this.m_pNativeObject);
    
            return ConvertStringToHex(ans); // Converts to Hex
        }
     public string ConvertStringToHex(string asciiString)
        {
            string hex = "";
            foreach (char c in asciiString)
            {
                int tmp = c;
                hex += String.Format("{0:x2}", (uint)System.Convert.ToUInt32(tmp.ToString()));
            }
            return hex;
        }
    
    不要重复发明轮子 您有什么理由不能使用Microsoft提供的类吗?您的答案存在一些问题,例如重新创建
    memcpy
    函数,该函数允许您在大约6行代码中执行内存复制功能,或者尝试将数据字符串封送为以null结尾的字符串。您应该只使用.NET提供的SHA1实现,除非有要求您必须自己创建

    如何在.NET中解决您的问题 您试图解决的问题实际上需要.NET中的3行代码,除非您需要使用.NET实现您自己的SHA1,这样做更有意义

    public static byte[] HashString(string inputString)
    {
        inputData = Encoding.ASCII.GetBytes("abc");
        var sha1 = new SHA1Managed();
    
        return sha1.ComputeHash(inputData);
    }
    

    不幸的是,您不能简单地从返回值封送数组。如果您需要多次调用它,我将从自定义封送拆收器开始:

    private class ReturnArrayMarshaller : ICustomMarshaler
    {
    
        public static ICustomMarshaler GetInstance(string cookie)
        {
            return new ReturnArrayMarshaller(cookie);
        }
    
        private readonly int byteCount;
    
        private ReturnArrayMarshaller(string cookie)
        {
            byteCount = int.Parse(cookie);
        }
    
        public void CleanUpManagedData(object ManagedObj) { throw new NotImplementedException(); }
    
        public void CleanUpNativeData(IntPtr pNativeData)
        {
            // release unmanaged return value if needed
        }
    
        public int GetNativeDataSize() { throw new NotImplementedException(); }
    
        public IntPtr MarshalManagedToNative(object ManagedObj) { throw new NotImplementedException(); }
    
        public object MarshalNativeToManaged(IntPtr pNativeData)
        {
            byte[] data = new byte[byteCount];
            Marshal.Copy(pNativeData, data, 0, data.Length);
            return data;
        }
    
    }
    
    并在签字声明中使用:

    [DllImport(@"hashLibrary.dll", CallingConvention = CallingConvention.Cdecl)]
    [return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(ReturnArrayMarshaller), MarshalCookie = "20")]
    public static extern byte[] CallReturnString(IntPtr pHashClassObject);
    
    <> >不要忘记在代码< >代码> dLimPurt<代码>中指定<代码> CalpIGNECTION.Cdecl <代码>,因为您在C++代码中没有使用<代码>
    另外,我相信您使用非托管库不仅仅是因为SHA1散列,因为大多数密码术都可以作为托管类使用。

    char*==string
    ,除非您要填充缓冲区,在这种情况下,请使用
    StringBuilder
    。但是,您返回的是一个指向本地数组的指针,该数组为否。当函数返回且对该数组的所有引用无效时,该数组将被清除。您返回的是一个
    无符号字符*
    ,该字符中可能没有NUL字节,并且在21位置也没有NUL字节。我怀疑你翻译成C#是在寻找一个以null结尾的字符串。需要了解如何使用
    SHA1::Result
    以获得进一步帮助。只需编辑,以便大家能够了解更多!谢谢仅供参考,从设计的角度来看,将静态数组从非托管代码传回托管代码不是一个好主意。如果多个线程可以访问该类(例如),会发生什么情况?最好是从托管->非托管中传递一组字节(和长度),并让C++代码填充字节。一分钟前我尝试过类似的方法:intptri;i=CallReturnString(这个.m_pNativeObject);字节[]ans=新字节[Marshal.SizeOf(i)];Marshal.Copy(i,ans,0,Marshal.SizeOf(i));我认为这与你的建议非常接近。但是它返回给我一个4个elemets字节的数组,元素和以前一样。用你的代码我得到了一个20个元素都是0的数组。同样,在我的代码中,前两个数字(字节上)应该是:36和14。但我得到231和13分。我从一开始就得到了这些数字-(@Roiw-您的代码只返回4个字节,因为Marshal.SizeOf(i)==4。在32位系统上,IntPtr是4个字节。