无法从C+;中检索正确的字符串+;代码。是否存在处理c#上无符号字符*的泛型类型?
这有点让人困惑,但我会尽力解释的 我试图在C++代码上运行C++ DLL。< /P> 在这个DLL上,我有一个方法,它应该返回一个20个字符的无符号字符*。表示4字节的5个“字”。(sha-1算法的输出) 我在C#项目中使用DLLIMPORT,如下所示:无法从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
[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个字节。