.NET 4.x Маршаллинг между C#-exe и С++-dll

Узнай цену своей работы

Формулировка задачи:

Приветствую. Имеется такой код (C#, exe), который обращается к C++ дллке (не /clr!), перекидывает ей структуру, чтобы та в свою очередь заполнила эту структуру данными и вернула её соответственно обратно в C# exe:
Листинг программы
  1. /// <summary>
  2. /// Represent info about particular file within a .torrent file.
  3. /// </summary>
  4. [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
  5. public struct TorrentInfoType_FilesList
  6. {
  7. // Full file path within a .torrent
  8. [MarshalAs(UnmanagedType.LPWStr)]
  9. public string filepath;
  10. // Filename of a file within a .torrent
  11. [MarshalAs(UnmanagedType.LPWStr)]
  12. public string filename;
  13. // Filesize of a file within a .torrent
  14. public Int64 filesize;
  15. }
  16. /// <summary>
  17. /// Represent general information about a .torrent file.
  18. /// </summary>
  19. /// <see cref="DLL->TorrentInfo.cpp/h"/>
  20. [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
  21. public struct TorrentInfoType
  22. {
  23. // Is torrent valid?
  24. [MarshalAs(UnmanagedType.U1)]
  25. public bool IsValid;
  26. // Torrent name/title.
  27. [MarshalAs(UnmanagedType.LPWStr)]
  28. public string name;
  29. // Torrent sha1 hash.
  30. [MarshalAs(UnmanagedType.LPWStr)]
  31. public string hash;
  32. // Torrent creation date
  33. public Int64 creationDate;
  34. // Torrent creator (usually, software дшлу uTorrent/3310)
  35. [MarshalAs(UnmanagedType.LPWStr)]
  36. public string creator;
  37. // Torrent author's comment.
  38. [MarshalAs(UnmanagedType.LPWStr)]
  39. public string comment;
  40. // Is torrent private?
  41. [MarshalAs(UnmanagedType.U1)]
  42. public bool IsPrivate;
  43. // Total number of bytes the torrent-file represents (all the files in it).
  44. public Int64 totalSize;
  45. // Files in torrent.
  46. public int filesCount;
  47. public int pieceLength;
  48. public int piecesCount;
  49. // Files list in .torrent
  50. [MarshalAs(UnmanagedType.LPArray)]
  51. public TorrentInfoType_FilesList[] files;
  52. }
  53. [DllImport(Globals.WRAPPER_DLL, CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Unicode)]
  54. private static extern TORRENT_ERROR dll_TorrentGetInfo(string filepath, IntPtr infoStruct);
  55. ...
  56. /// <summary>
  57. /// Retrieves .torrent information (creator, comment, files count and so on)
  58. /// </summary>
  59. /// <param name="filepath">full path to .torrent file (ex. C:\torr.torrent)</param>
  60. /// <returns></returns>
  61. public static bool GetTorrentInfo(string filepath, out TorrentInfoType info)
  62. {
  63. // Init structure with default values.
  64. info = new TorrentInfoType()
  65. {
  66. IsValid = false,
  67. name = "Unknown",
  68. hash = "",
  69. creationDate = 0,
  70. creator = "Unknown creator",
  71. comment = "",
  72. IsPrivate = false,
  73. totalSize = 0,
  74. filesCount = 0,
  75. pieceLength = 0,
  76. piecesCount = 0,
  77. files = new TorrentInfoType_FilesList[]
  78. {
  79. }
  80. };
  81. // Is .torrent exists?
  82. if (!File.Exists(filepath))
  83. {
  84. AppCore.ShowErr(
  85. String.Format(AppCore.LS("Error.FileNotExists"), filepath)
  86. );
  87. return false;
  88. }
  89. // Allocate structure to be ready marshalled in/out DLL.
  90. int tempSize = Marshal.SizeOf(typeof(TorrentInfoType));
  91. IntPtr pInfo = Marshal.AllocHGlobal(tempSize);
  92. Marshal.StructureToPtr(info, pInfo, false);
  93. // Query info.
  94. var err = dll_TorrentGetInfo(filepath, pInfo);
  95. if (err == TORRENT_ERROR.TE_INFO_INVALIDTORRENT)
  96. {
  97. Marshal.FreeHGlobal(pInfo);
  98. return false;
  99. }
  100. // Update info structure with received data.
  101. info = (TorrentInfoType)(Marshal.PtrToStructure(pInfo, typeof(TorrentInfoType)));
  102. // Free memory.
  103. Marshal.FreeHGlobal(pInfo);
  104. DumpTorrentInfoData(info);
  105. return true;
  106. }
После того, как было добавлено (

так как появилась необходимость получить список файлов в торренте и отдать его вместе с базовыми данными по нему, которые уже и так возвращаются нормально

) в C# TorrentInfoType структуру вот этот кусок (

и в С++ часть свой аналог - std::vector<TorrentInfoType_FilesLi st>... - соответственно тоже

):
Листинг программы
  1. // Files list in .torrent
  2. [MarshalAs(UnmanagedType.LPArray)]
  3. public TorrentInfoType_FilesList[] files;
Это стало продуцировать на этой строке:
Листинг программы
  1. int tempSize = Marshal.SizeOf(typeof(TorrentInfoType));
...вот такую ошибку: Marshal.SizeOf - cannot be marshaled as an unmanaged structure… Укажите пожалуйста, что не делаю не так в этой ситуации? :-\ Наверное многое, ибо всего 3-4 месяца изучаю C# с С++, так что не пинайте сильно пжалста И просто для референса, на стороне С++ структуры выглядят так:
Листинг программы
  1. struct TorrentInfoType_FilesList
  2. {
  3. wchar_t* filepath;
  4. wchar_t* filename;
  5. long long filesize;
  6. };
  7. struct TorrentInfoType
  8. {
  9. bool IsValid;
  10. wchar_t* name;
  11. wchar_t* hash;
  12. long long creationDate;
  13. wchar_t* creator;
  14. wchar_t* comment;
  15. bool IsPrivate;
  16. long long totalSize;
  17. int filesCount;
  18. int pieceLength;
  19. int piecesCount;
  20. std::vector<TorrentInfoType_FilesList> files;
  21. };
И потом в С++ной части в функции dll_TorrentGetInfo я вызываю функцию для копирования в структуру которая потом возвращается в C#:
Листинг программы
  1. void TorrentInfo::CopyInfo(TorrentInfoType* dest) const
  2. {
  3. dest->IsValid = IsValid();
  4. dest->name = _wcsdup(GetNameW().c_str());
  5. dest->hash = _wcsdup(GetHashW().c_str());
  6. dest->creationDate = GetCreationDate();
  7. dest->creator = _wcsdup(GetCreatorW().c_str());
  8. dest->comment = _wcsdup(GetCommentW().c_str());
  9. dest->IsPrivate = IsPrivate();
  10. dest->totalSize = GetTotalSize();
  11. dest->filesCount = GetFilesCount();
  12. dest->pieceLength = GetPieceLength();
  13. dest->piecesCount = GetPiecesCount();
  14. // TODO: Fill files list.
  15. // ...
  16. }

Решение задачи: «.NET 4.x Маршаллинг между C#-exe и С++-dll»

textual
Листинг программы
  1.  info = new TorrentInfoType();
  2.    .........................................
  3.  .............................................
  4.  
  5. // Update info structure with received data.
  6.  info = (TorrentInfoType)(Marshal.PtrToStructure(pInfo, typeof(TorrentInfoType)));

ИИ поможет Вам:


  • решить любую задачу по программированию
  • объяснить код
  • расставить комментарии в коде
  • и т.д
Попробуйте бесплатно

Оцени полезность:

14   голосов , оценка 4.286 из 5

Нужна аналогичная работа?

Оформи быстрый заказ и узнай стоимость

Бесплатно
Оформите заказ и авторы начнут откликаться уже через 10 минут
Похожие ответы