信息交流、传播、提炼

nice to meet you

博客园 首页 新随笔 联系 订阅 管理

C#有时需要调用C++等语言编写发布的DLL,这就涉及到一个问题,如何将将非托管内存指针中的数据复制到托管变量中来?微软提供了Marshal.Copy等方法,以实现类似的需求。

1)将非托管内存指针中的数据复制到托管 32 位有符号整数数组。

public static void Copy (
 IntPtr source,
 int[] destination,
 int startIndex,
 int length
)

2)

将数据从非托管内存块封送到新分配的指定类型的托管对象
C#调用C++ DLL(返回结构数组指针)
C++代码:
typedef struct TRANSACTION
{
 char account[19];
 int maxNum;
 char startDate[16];
 char endDate[16];
} TRANSACTION;

typedef struct QUERY
{
 int id;
 int itemAmount;
 int gold;
 int silver;
 char itemName[30];
}QUERY;

extern "C " _declspec(dllexport) QUERY* QueryTransactionHistory(DWORD dwIP,int nPort,TRANSACTION * pTran, int* outNum,int* nErrorCode) {
 cout << "dwIP = " << dwIP << ", nPort = " << nPort << ", pTran -> maxNum = " << pTran -> maxNum << endl;
 cout << "pTran -> account = " << pTran -> account << ", pTran -> startDate = " << pTran -> startDate << ", pTran -> endDate = " << pTran -> endDate << endl;
 
 QUERY* ret = (QUERY* )malloc(sizeof(QUERY) * 2);
 ret[0].id = 0;
 ret[0].gold = ret[0].silver = ret[0].itemAmount = 1;
 strcpy(ret[0].itemName, "Item0 ");
 
 ret[1].id = 1;
 ret[1].gold = ret[1].silver = ret[1].itemAmount = 2;
 strcpy(ret[1].itemName, "Item1 ");
 
 (*outNum) = 2;
 (*nErrorCode) = 0;
 return ret;
}

C#代码:
[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Ansi)]
public class TRANSACTION
{
  [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 19)]
  public string   account;

  public int maxNum;

  [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)]
  public string startDate;

  [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)]
  public string endDate;
}

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public class QUERY
{
  public int id;
  public int itemAmount;
  public int gold;
  public int silver;

  [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 30)]
  public string itemName;
}

class Program
{
  [DllImport( "CPPDLL.DLL ", CallingConvention = CallingConvention.StdCall)]
  public extern static IntPtr QueryTransactionHistory(uint swIP, int nPort, TRANSACTION pTran, out int cnt, out int nErrCode);

  static void Main(string[] args)
  {
  int cnt, errCode;
  TRANSACTION tran = new TRANSACTION();

  tran.account   = "account ";
  tran.endDate   = "endDate ";
  tran.startDate   = "startDate ";
  tran.maxNum     = 50;

  //get retrun value as IntPtr
  IntPtr ptr = QueryTransactionHistory(0, 0, tran, out cnt, out errCode);
  Console.WriteLine( "============ CS =============== ");
  Console.WriteLine( "Count = {0}, errCode = {1} ", cnt, errCode);

  IntPtr head = ptr;
  for (int i = 0; i < cnt; ++i)
  {
    //extract struct from pointer
    QUERY q = (QUERY)Marshal.PtrToStructure(ptr, typeof(QUERY));
    Console.WriteLine( "id = {0}, gold = {1}, silver = {2}, itemAmount = {3}, itemName = {4} ",
        q.id, q.gold, q.silver, q.itemAmount, q.itemName);

    //move pointer by sizeof(QUERY) to the next one
    //WARNING: assume 32 bit machine!!!!!!
    ptr = (IntPtr)(ptr.ToInt32() + Marshal.SizeOf(typeof(QUERY)));
  }
  //TODO: need to free memory
  }
}

将非托管内存指针中的数据复制到托管 32 位有符号整数数组。
public static void Copy (
 IntPtr source,
 int[] destination,
 int startIndex,
 int length
)

 

posted on 2011-12-11 23:14  seeyou  阅读(1474)  评论(0)    收藏  举报