c# 调用 c++ 的DLL 问题
--------------------编程问答-------------------- 没人会吗?急啊--------------------编程问答-------------------- 请高手指点,请高手指点 --------------------编程问答-------------------- 无法读写受保护的内存,指针不对。
param.lpBuffer 这个你那里来的?直接c++的指针发过来的么?
发消息拷贝数据用WM_COPYDATA。 --------------------编程问答--------------------
param.lpBuffer的结构体是:
[StructLayout(LayoutKind.Sequential)]
public struct GlyParam
{
public int handle;
public int dwErrorCode;
public int dwMessageID;
public int dwRequestID;
public int ulSize;
public IntPtr lpBuffer;
public string szParamName;
}
而param的值是通过回调函数返回来的:
private void FrmCallback(ref GlyParam returnParam)
{
param = returnParam;
。。。
}
param.lpBuffer的值是个指针地址:113476728
现在就是要把param.lpBuffer转换成GlyDepositCounter结构.
GlyDepositCounter glyDepositCounter = (GlyDepositCounter)Marshal.PtrToStructure(param.lpBuffer, typeof(GlyDepositCounter));
这个时候出错:Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
--------------------编程问答-------------------- dll和主程序的指针不能直接共享的,感觉会有问题,没这么用过。 --------------------编程问答-------------------- [MarshalAs(UnmanagedType.LPWStr)]//根据c++中的类型设置成一样的
public string szParamName;
--------------------编程问答-------------------- 1、GlyDepositCounter里面的定义又套了结构,而且还套了几层,这样会导致Marshal在分配大小时,无法计算。你可以用Marsh.sizeof(typeof(GlyDepositCounter))来测试看看。因为无法分配大小,自然就读写不进去了。
2、可以考虑将需要套结构的地方转换成类来做,然后进行封装。到最终没有套结构的地方,再使用字节转换成结构。这样才比较保险。
public class ObjectSp
{
#region bytesToStruct
/// <summary>
/// Byte array to struct or classs.
/// </summary>
/// <param name="bytes">Byte array</param>
/// <param name="type">Struct type or class type.
/// Egg:class Human{...};
/// Human human=new Human();
/// Type type=human.GetType();</param>
/// <param name="startIndex">Byte array start index.</param>
/// <returns>Destination struct or class.</returns>
public static object bytesToStruct(byte[] bytes, Type type, int startIndex = 0)
{
int size = Marshal.SizeOf(type);//Get size of the struct or class.
if (bytes.Length < size)
{
return null;
}
IntPtr structPtr = Marshal.AllocHGlobal(size);//Allocate memory space of the struct or class.
Marshal.Copy(bytes, startIndex, structPtr, size);//Copy byte array to the memory space.
object obj = Marshal.PtrToStructure(structPtr, type);//Convert memory space to destination struct or class.
Marshal.FreeHGlobal(structPtr);//Release memory space.
return obj;
}
#endregion
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
public class GlyDepositCounter
{
public uint EventNumber;
public Tm Time;
public uint dwSquentialNo;
public uint dwUserID;
public GlyCounters DepositData;
public GlyDepositCounter(byte[] buff)
{
int offset = 0;
EventNumber = BitConverter.ToUInt32(buff, 0);
offset += sizeof(uint);
Time = (Tm)ObjectSp.bytesToStruct(buff, typeof(Tm), offset);
offset += Marshal.SizeOf(typeof(Tm));
dwSquentialNo = BitConverter.ToUInt32(buff, offset);
offset += sizeof(uint);
dwUserID = BitConverter.ToUInt32(buff, offset);
offset += sizeof(uint);
DepositData = 易做图yDepositData(buff, offset);
}
private GlyCounters 易做图yDepositData(byte[] buff, int offset)
{
GlyCounters DepositData = null;
//仿照GlyDepositCounter进一步分析DepositData
return DepositData;
}
}
3、建议增加CharSet和Pack参数,这样才能保证字节的对齐。比如[StructLayout(LayoutKind.Sequential,CharSet=CharSet.Ansi,Pack=1)]
补充:.NET技术 , C#