.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)));
ИИ поможет Вам:
- решить любую задачу по программированию
- объяснить код
- расставить комментарии в коде
- и т.д