С Новым годом! Форум программистов, компьютерный форум, киберфорум
C# для начинающих
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.67/6: Рейтинг темы: голосов - 6, средняя оценка - 4.67
0 / 0 / 0
Регистрация: 22.06.2017
Сообщений: 1
1
.NET 4.x

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

22.06.2017, 15:21. Показов 1120. Ответов 4

Author24 — интернет-сервис помощи студентам
Приветствую.
Имеется такой код (C#, exe), который обращается к C++ дллке (не /clr!), перекидывает ей структуру, чтобы та в свою очередь заполнила эту структуру данными и вернула её соответственно обратно в C# exe:
Кликните здесь для просмотра всего текста
https://pastebin.com/DPuBeqBX
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
        /// <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>... - соответственно тоже):
C#
1
2
3
// Files list in .torrent
[MarshalAs(UnmanagedType.LPArray)]
public TorrentInfoType_FilesList[] files;
Это стало продуцировать на этой строке:
C#
1
int tempSize = Marshal.SizeOf(typeof(TorrentInfoType));
...вот такую ошибку: Marshal.SizeOf - cannot be marshaled as an unmanaged structure…

Укажите пожалуйста, что не делаю не так в этой ситуации? :-\
Наверное многое, ибо всего 3-4 месяца изучаю C# с С++, так что не пинайте сильно пжалста

И просто для референса, на стороне С++ структуры выглядят так:
Кликните здесь для просмотра всего текста
https://pastebin.com/43RDUdQx
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
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;
};


И потом в С++ной части в функции dll_TorrentGetInfo я вызываю функцию для копирования в структуру которая потом возвращается в C#:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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.
  // ...
}
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
22.06.2017, 15:21
Ответы с готовыми решениями:

Передача строк между Dll между Exe
Подскажите алгоритм предачи строк между динамической библиотекой и исполняемым файлом. Мне...

Svchost.exe, onion.exe, openvg.exe torrc и куча dll и cl, а также папка tor в Roaming

Как множество dll собрать в один dll или exe файл?
Сделал тестовый проектик по работе с БД (Entity Framework), скомпилировал и как глянул в папку...

Куда компилятор csc.exe кладёт скомпилированные .exe/.dll?
Куда компилятор csc.exe кладёт скомпилированные .exe/.dll? Есть батник, компиляция проекта в Visual...

4
1498 / 1213 / 821
Регистрация: 29.02.2016
Сообщений: 3,628
22.06.2017, 19:08 2
https://stackoverflow.com/ques... in-c-sharp
https://www.codeproject.com/Ar... Applicatio

Добавлено через 2 минуты
https://www.dotnetperls.com/dllimport
0
0 / 0 / 0
Регистрация: 18.02.2015
Сообщений: 7
22.06.2017, 21:45 3
afront
Вы видимо, перед ответом, не читали сообщение автора от слова совсем?
Он интересуется по вполне конкретной проблеме - как прокинуть в C++ из C# - структуру, в которой есть массив на структуру. Ибо, как он уже заметил, без конкретно этого куска - у него работает всё нормально.
0
278 / 186 / 75
Регистрация: 12.04.2017
Сообщений: 1,088
Записей в блоге: 2
23.06.2017, 15:47 4
Ваш код работает если:
Цитата Сообщение от bnetrealm Посмотреть сообщение
// Files list in .torrent [MarshalAs(UnmanagedType.LPArray)] public TorrentInfoType_FilesList[] files;
Тип массива заменить на UnmanagedType.ByValArray, элемент массива UnmanagedType.Struct.
и указать размер массива
C#
1
2
3
  // Files list in .torrent
  [MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.Struct, SizeConst = 256)]
   public TorrentInfoType_FilesList[] files;


Кстати, зачем заполнять поля структуры, если вы их всё равно прихлопните?


C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
   info = new TorrentInfoType()
            {
                IsValid = false,
                name = "Unknown",
               ..............
                pieceLength = 0,
                piecesCount = 0,
                files = new TorrentInfoType_FilesList[]
                {
                    
                }
            };
 
   .........................................
 .............................................
 
 
            // Update info structure with received data.
            info = (TorrentInfoType)(Marshal.PtrToStructure(pInfo, typeof(TorrentInfoType)));
Ведь достаточно конструктора по умолчанию.
Вероятно вы хотели так.

C#
1
2
3
4
5
6
 info = new TorrentInfoType();
   .........................................
 .............................................
 
// Update info structure with received data.
 info = (TorrentInfoType)(Marshal.PtrToStructure(pInfo, typeof(TorrentInfoType)));
После этого если сообщения "разбалансирован стэк", смотрите что у вас там
за соглашения о вызовах .
Цитата Сообщение от bnetrealm Посмотреть сообщение
CallingConvention = CallingConvention.StdCall
может на CallingConvention.Cdecl изменить.


Ещё момент напрягает. Попахивает утечкой памяти.
Цитата Сообщение от bnetrealm Посмотреть сообщение
void TorrentInfo::CopyInfo(TorrentInfoType* dest) const { dest->IsValid = IsValid(); dest->name = _wcsdup(GetNameW().c_str()); dest->hash = _wcsdup(GetHashW().c_str());
_wcsdup вызывает функцию malloc.

А выделенную malloc память требуется освобождать.
0
Computershik
23.06.2017, 17:19     .NET 4.x Маршаллинг между C#-exe и С++-dll
  #5

Не по теме:

Опять очередную торрентокачалку с кучей рекламы пилят...

0
23.06.2017, 17:19
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
23.06.2017, 17:19
Помогаю со студенческими работами здесь

Возможно ли собрать .exe и несколько .dll в один .exe?
Просто написал программку, получилось &gt;6 .dll файлов, с этим ничего нельзя поделать без &quot;отучения...

AppModule.exe - точка входа в процедуру cuLaunchKernel_ptsz не найдена в библиотеке DLL nvcuda.dll
Добрый день, После серии неудачных экспериментов с установкой и попыткой починить программы имею...

Dll файл в exe файле. Вшить dll libcurl
Проблема такая что приходится таскать всегда libcurl.dll с собой. Надо все носить в одном exe....

EXE & DLL, DLL не запускается, 500 ошибка
Делаю EXE, скрипт простой, всё работает, на Apache и FPServer. Компилирую в DLL, закидываю на...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
5
Ответ Создать тему
Новые блоги и статьи
Что такое CQRS и как это реализовать на C# с MediatR
InfoMaster 15.01.2025
Концепция CQRS и её роль в современной разработке В современном мире разработки программного обеспечения архитектурные паттерны играют ключевую роль в создании масштабируемых и поддерживаемых. . .
Как настроить CI/CD с Azure DevOps
InfoMaster 15.01.2025
CI/ CD, или непрерывная интеграция и непрерывное развертывание, представляет собой современный подход к разработке программного обеспечения, который позволяет автоматизировать и оптимизировать процесс. . .
Как настроить CI/CD с помощью Jenkins
InfoMaster 15.01.2025
Введение в CI/ CD и Jenkins В современной разработке программного обеспечения непрерывная интеграция (CI) и непрерывная доставка (CD) стали неотъемлемыми элементами процесса создания качественных. . .
Как написать микросервис на Go/Golang с Kafka и GitHub CI/CD
InfoMaster 14.01.2025
Определение микросервиса, преимущества использования Go/ Golang Микросервис – это архитектурный подход к разработке программного обеспечения, при котором приложение состоит из небольших, независимо. . .
Как написать микросервис с нуля на C# с RabbitMQ, CQRS и CI/CD
InfoMaster 14.01.2025
В современном мире разработки программного обеспечения микросервисная архитектура стала стандартом де-факто для создания масштабируемых и гибких приложений. Этот архитектурный подход предполагает. . .
Как создать интернет-магазин на PHP и JavaScript
InfoMaster 14.01.2025
В современном мире электронная коммерция стала неотъемлемой частью бизнеса. Создание собственного интернет-магазина открывает широкие возможности для предпринимателей, позволяя достичь большей. . .
Как написать Тетрис на Ассемблере
InfoMaster 14.01.2025
Тетрис – одна из самых узнаваемых и популярных компьютерных игр, созданная в 1984 году советским программистом Алексеем Пажитновым. За прошедшие десятилетия она завоевала симпатии миллионы людей по. . .
Как создать игру "Танчики" на Unity3d и C#
InfoMaster 14.01.2025
Разработка игр – это увлекательный процесс, сочетающий в себе творчество и технические навыки. В этой статье мы рассмотрим создание классической игры "Танчики" с использованием Unity3D и языка. . .
Организую платный онлайн микро-курс по доработке Android-клиента Telegram
_Ivana 14.01.2025
Официальная версия и распространенные форки не полностью устраивают? Сделай свою кастомную версию клиента! 4 занятия по 2 часа (2 недели пн, ср 19:00-21:00 по Москве). Первое вводное занятие. . .
Как создать приложение для фитнеса для iOS/iPhone на Kotlin
InfoMaster 14.01.2025
Создание собственного фитнес-приложения — это не только захватывающий, но и полезный процесс, ведь оно может стать вашим верным помощником на пути к здоровому и активному образу жизни. В современных. . .
Как создать приложение магазина для iOS/iPhone на Swift
InfoMaster 14.01.2025
Введение в разработку iOS-приложений Разработка приложений для iPhone и других устройств на базе iOS открывает огромные возможности для создания инновационных мобильных решений. В данной статье мы. . .
Это работает. Скорость асинхронной логики велика. Вопрос видимо останется в стабильности. Плата - огонь!
Hrethgir 13.01.2025
По прошлому проекту в Logisim Evolution https:/ / www. cyberforum. ru/ blogs/ 223907/ blog8781. html прилагаю файл архива проекта в Gowin Eda. Восьмибитный счётчик из сумматора+ генератор сигнала. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru