日期:2014-05-18  浏览次数:21024 次

C#调用C++ dll 函数实现内存拷贝的问题。
C++中有一个函数ZZZ(char* buf);其主要作用是将一个结构体指针structA赋值给buf指针。用到memcpy(buf, structA, len);这样执行完该函数后,运行Struct structB=(Struct)buf后可得到该结构体数据。
char buf[1000];
char* pbs=buf;
zzz(pbs);
structB=(Struct)pbs;

我需要的是在C#中调用该dll文件中的ZZZ函数,从而得到structA的值。
请问在C#中该如何进行函数申明,如果调用该函数得到structA的值。
1)我查询过MSDN,指示char*应该被转换成string或StringBuild,我试过,但是得到的string类型的pbs长度为初始值,根本没有得到任何数据。我怀疑char*转换成string是指字符串的情况。可是这里的char* buf是指内存空间。
2)我觉得是不是可以将char*等同于void*,那么根据MSDN,就应该转换成IntPtr。于是我这样写:
char[] buf=new char[1000];
IntPtr pbs=buf;<===但是这里就编译出错了,C#不支持这样的转换。

特意来此请教,该如何实现这个功能。多谢!

------解决方案--------------------
c++ char对应c#的byte,可以
byte[] buf = new byte[1000];
zzz(ref buf);
structB=(struct_type)BytesToStruct(buf,typeof(struct_type));

public static object BytesToStruct(byte[] bytes, Type type)
{
//得到结构体的大小
int size = Marshal.SizeOf(type);
//byte数组长度小于结构体的大小
if (size > bytes.Length)
{
//返回空
return null;
}
//分配结构体大小的内存空间
IntPtr structPtr = Marshal.AllocHGlobal(size);
//将byte数组拷到分配好的内存空间
Marshal.Copy(bytes, 0, structPtr, size);
//将内存空间转换为目标结构体
object obj = Marshal.PtrToStructure(structPtr, type);
//释放内存空间
Marshal.FreeHGlobal(structPtr);
//返回结构体
return obj;
}

------解决方案--------------------
方法有好几种。最简单直接的是声明为zzz(ref Struct buf),调用前new Struct()后引用传递结构即可。这也是我不理解你的C++代码为什么不是直接定义一个结构传结构地址,而是转个圈定义一个数组?
和你的C++代码形式上最接近的做法,正是如你说的声明为IntPtr:
C# code
            sbyte[] buf = new sbyte[1000];    //不是对应char
            GCHandle gch = GCHandle.Alloc(buf, GCHandleType.Pinned);    //固定
            IntPtr pbs = Marshal.UnsafeAddrOfPinnedArrayElement(buf, 0);
            zzz(pbs);
            Struct StructB = Marshal.PtrToStructure(pbs, typeof(Struct));
            gch.Free();