无法从C++代码中检索正确的字符串.是否有一种通用类型用于处理c#上的无符号字符*
Cant retrieve right string from C++ code. Is there a generic type for handling unsigned char* on c#?
这很令人困惑,但我会尽力解释!
我正试图在我的C#代码上运行一个C++DLL。
在这个DLL上,我有一个方法,应该返回一个20个字符的无符号字符*。表示4个字节的5个"单词"。(sha-1算法的输出)
我在C#项目中使用DLLIMPORT,如下所示:
[DllImport("hashLibrary.dll", CharSet = CharSet.Ansi)]
static private extern string CallReturnString(IntPtr pHashClassObject);
这应该返回5个WORDS字符串。
这是我的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] = ' ';
return s_out;
}
在这段代码中,我试图从H中获取所有字节,并添加一个将传递给C#代码的字符。
H声明为:unsigned H[5];
它几乎可以工作,但出于某种原因,有些组合会给我带来疯狂的结果,比如C#上的22个成员字符串,并且值都是错误的。
我认为这与C#和C++上的一些不同类型的变量有关如果我只能像C++代码中那样从char*中获得所有字节,那就太棒了
有人知道怎么做吗?
谢谢大家!
编辑:
一般工作流程为:
- 我的Windows窗体应用程序从C++类创建一个新类:
HashWrapper hash = new HashWrapper();
- 我的windows窗体应用程序向C++(它是SHA-1算法类)发送种子:
hash.SendInput("abc");
- 我的windows窗体应用程序要求获得c++算法的结果:
string output = hash.ReturnString();
在这里,我将把我调用的方法放在最上面:
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;
}
不幸的是,您不能简单地根据返回值封送数组。如果你需要多次调用它,我会从自定义编组器开始:
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);
不要忘记在DllImport
中指定CallingConvention.Cdecl
,因为您在C++代码中没有使用__stdcall
修饰符。
附言:我认为您使用非托管库并不是因为SHA1哈希,而是因为大多数密码学都可以作为托管类使用。
不要重新设计轮子
你为什么不能使用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);
}
- 有没有一种方法可以通过"typedef"为重新定义的基本类型定义特征和强制转换运算符
- 在运行时检查继承是否只有一种类型和 void*
- 文本冒险游戏 - 如何区分一种项目类型与另一种项目类型以及如何构建项目类/子类
- 当 c++ 需要一种数据类型并获取另一种数据类型时会发生什么?
- 在硬件SIMD矢量指针和相应类型之间进行"interpret_cast"是一种未定义的行为吗
- 另一种类型的智能ptr,比如具有弱refs的unique_ptr
- void* 数组将元素转换为另一种类型
- 使用字节向量作为其他类型的原始存储是一种好的做法吗
- 将一种数据类型的向量复制到同一数据类型的结构向量中的有效方法是什么
- 将一种类型的比特重新解释为不同类型的比特的技术
- 有没有一种方法可以使用SFINAE来检测一个类型是否实现了给定的抽象基类
- 在枚举类型上使用std::max是不是一种糟糕的做法
- 为什么需要类型名称,即使似乎足以推断名称应该是一种类型?
- 在 c++ 中将一种结构类型分配给另一种类型
- 将空基类优化对象强制转换为另一种类型是否会破坏严格的别名?
- 我怎样才能让编译器推导出一种类型的 nullptr
- 如何测试指针类型是否可以安全地转换为另一种指针类型?
- 有没有一种很好的方法来实现具有默认失败情况的条件类型?
- 一种类型的多个 cv 分解
- 如何将对象定义为一种类型,然后再将其声明为子类型