.NET 4.x Маршаллинг между C#-exe и С++-dll
Формулировка задачи:
Приветствую.
Имеется такой код (C#, exe), который обращается к C++ дллке (не /clr!), перекидывает ей структуру, чтобы та в свою очередь заполнила эту структуру данными и вернула её соответственно обратно в C# exe:
После того, как было добавлено (Это стало продуцировать на этой строке:
...вот такую ошибку: Marshal.SizeOf - cannot be marshaled as an unmanaged structure…
Укажите пожалуйста, что не делаю не так в этой ситуации? :-\
Наверное многое, ибо всего 3-4 месяца изучаю C# с С++, так что не пинайте сильно пжалста
И просто для референса, на стороне С++ структуры выглядят так:
И потом в С++ной части в функции dll_TorrentGetInfo я вызываю функцию для копирования в структуру которая потом возвращается в C#:
/// <summary> /// Represent info about particular file within a .torrent file. /// </summary> [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] public struct TorrentInfoType_FilesList { // Full file path within a .torrent [MarshalAs(UnmanagedType.LPWStr)] public string filepath; // Filename of a file within a .torrent [MarshalAs(UnmanagedType.LPWStr)] public string filename; // Filesize of a file within a .torrent public Int64 filesize; } /// <summary> /// Represent general information about a .torrent file. /// </summary> /// <see cref="DLL->TorrentInfo.cpp/h"/> [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] public struct TorrentInfoType { // Is torrent valid? [MarshalAs(UnmanagedType.U1)] public bool IsValid; // Torrent name/title. [MarshalAs(UnmanagedType.LPWStr)] public string name; // Torrent sha1 hash. [MarshalAs(UnmanagedType.LPWStr)] public string hash; // Torrent creation date public Int64 creationDate; // Torrent creator (usually, software дшлу uTorrent/3310) [MarshalAs(UnmanagedType.LPWStr)] public string creator; // Torrent author's comment. [MarshalAs(UnmanagedType.LPWStr)] public string comment; // Is torrent private? [MarshalAs(UnmanagedType.U1)] public bool IsPrivate; // Total number of bytes the torrent-file represents (all the files in it). public Int64 totalSize; // Files in torrent. public int filesCount; public int pieceLength; public int piecesCount; // Files list in .torrent [MarshalAs(UnmanagedType.LPArray)] public TorrentInfoType_FilesList[] files; } [DllImport(Globals.WRAPPER_DLL, CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Unicode)] private static extern TORRENT_ERROR dll_TorrentGetInfo(string filepath, IntPtr infoStruct); ... /// <summary> /// Retrieves .torrent information (creator, comment, files count and so on) /// </summary> /// <param name="filepath">full path to .torrent file (ex. C:\torr.torrent)</param> /// <returns></returns> public static bool GetTorrentInfo(string filepath, out TorrentInfoType info) { // Init structure with default values. info = new TorrentInfoType() { IsValid = false, name = "Unknown", hash = "", creationDate = 0, creator = "Unknown creator", comment = "", IsPrivate = false, totalSize = 0, filesCount = 0, pieceLength = 0, piecesCount = 0, files = new TorrentInfoType_FilesList[] { } }; // Is .torrent exists? if (!File.Exists(filepath)) { AppCore.ShowErr( String.Format(AppCore.LS("Error.FileNotExists"), filepath) ); return false; } // Allocate structure to be ready marshalled in/out DLL. int tempSize = Marshal.SizeOf(typeof(TorrentInfoType)); IntPtr pInfo = Marshal.AllocHGlobal(tempSize); Marshal.StructureToPtr(info, pInfo, false); // Query info. var err = dll_TorrentGetInfo(filepath, pInfo); if (err == TORRENT_ERROR.TE_INFO_INVALIDTORRENT) { Marshal.FreeHGlobal(pInfo); return false; } // Update info structure with received data. info = (TorrentInfoType)(Marshal.PtrToStructure(pInfo, typeof(TorrentInfoType))); // Free memory. Marshal.FreeHGlobal(pInfo); DumpTorrentInfoData(info); return true; }
так как появилась необходимость получить список файлов в торренте и отдать его вместе с базовыми данными по нему, которые уже и так возвращаются нормально
) в C# TorrentInfoType структуру вот этот кусок (и в С++ часть свой аналог - std::vector<TorrentInfoType_FilesLi st>... - соответственно тоже
):// Files list in .torrent [MarshalAs(UnmanagedType.LPArray)] public TorrentInfoType_FilesList[] files;
int tempSize = Marshal.SizeOf(typeof(TorrentInfoType));
struct TorrentInfoType_FilesList { wchar_t* filepath; wchar_t* filename; long long filesize; }; struct TorrentInfoType { bool IsValid; wchar_t* name; wchar_t* hash; long long creationDate; wchar_t* creator; wchar_t* comment; bool IsPrivate; long long totalSize; int filesCount; int pieceLength; int piecesCount; std::vector<TorrentInfoType_FilesList> files; };
void TorrentInfo::CopyInfo(TorrentInfoType* dest) const { dest->IsValid = IsValid(); dest->name = _wcsdup(GetNameW().c_str()); dest->hash = _wcsdup(GetHashW().c_str()); dest->creationDate = GetCreationDate(); dest->creator = _wcsdup(GetCreatorW().c_str()); dest->comment = _wcsdup(GetCommentW().c_str()); dest->IsPrivate = IsPrivate(); dest->totalSize = GetTotalSize(); dest->filesCount = GetFilesCount(); dest->pieceLength = GetPieceLength(); dest->piecesCount = GetPiecesCount(); // TODO: Fill files list. // ... }
Решение задачи: «.NET 4.x Маршаллинг между C#-exe и С++-dll»
textual
Листинг программы
info = new TorrentInfoType(); ......................................... ............................................. // Update info structure with received data. info = (TorrentInfoType)(Marshal.PtrToStructure(pInfo, typeof(TorrentInfoType)));
ИИ поможет Вам:
- решить любую задачу по программированию
- объяснить код
- расставить комментарии в коде
- и т.д