powered by simpleCommunicator - 2.0.52     © 2025 Programmizd 02
Форумы / WinForms, .Net Framework [игнор отключен] [закрыт для гостей] / Получить изображение неизвестного размера (байтовый массив) из dll C++ --> C#
12 сообщений из 12, страница 1 из 1
Получить изображение неизвестного размера (байтовый массив) из dll C++ --> C#
    #39437520
Arbit
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Здравствуйте уважаемые Гуру!

Подскажите пожалуйста новичку как правильно осуществить сабж?

DLL (C++ ) читает поле BLOB из базы SQLite в байтовый массив.
Размер этого массива заранее неизвестен.
Нужно передать массив в проект С# и отобразить изображение в PictureBox

Вариант использовать нетовскую dll для работы с базой пожалуйста не предлагайте!

Попутно вопрос -
1 как скопировать данные в новый массив (исходя из полученного указателя) сильно не пинайте!
2. как очистить память выделенную под массив в коде dll (желательного без повторного вызова DLL)

В голову приходит только такая мысль (если она дурная, то поправьте пожалуйста):
C#
Код: 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.
public partial class frmImagesMenager : Form
{
     [DllImport(@"D:\ProjectsC#\SQLite\Debug\sqlite_db.dll")]
     public static extern byte* DLL_LoadImage(int ImgId, ref int buffsize);
 
     public frmImagesMenager()
     {
            InitializeComponent();
     }
 
     private void GetImage()
     {
           int ImgId = 10;
           int buffsize = 0;
 
           byte* pArrImg = DLL_LoadImage(ImgId, out int buffsize);
           int[] NewImg = new int[buffsize];
 
           //здесь нужно скопировать полученные по указателю данные в новый массив (как?)
           //здесь очистить память, выделенную в DLL   (как?)                                                                               
 
           MemoryStream ms = new MemoryStream(NewImg);
           this.PictureBox.Image = Image.FromStream(ms);
           this.PictureBox.SizeMode = PictureBoxSizeMode.StretchImage;
         }
 
}


C++
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
extern "C" __declspec(dllexport) byte* DLL_LoadImage(int ImgID, int *size)
{
sqlite3 *db;
sqlite3_stmt *pStmt; 
sqlite3_prepare(db, strSQL, -1, &pStmt, NULL)
int rc = sqlite3_step(pStmt);
 
int size = sqlite3_column_bytes(pStmt, 0);
byte* buff = new byte[size];
memmove(&buff[0], sqlite3_column_blob(pStmt, 0), size);
 
return  buff;

}



Заранее благодарен откликнувшимся
...
Рейтинг: 0 / 0
Получить изображение неизвестного размера (байтовый массив) из dll C++ --> C#
    #39437623
Фотография Изопропил
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Arbit1 как скопировать данные в новый массив (исходя из полученного указателя) сильно не пинайте!

возвращаемый тип - лучше не byte* , а IntPtr
копирование IntPtr в массив - Marshal.Copy(...)

Arbit2. как очистить память выделенную под массив в коде dll (желательного без повторного вызова DLL)
её незачем выделять, просто вернуть результат sqlite3_column_blob (а эту память освободит сам sqlite)


а промежуточная dll - не нужна.
здесь есть готовая c# функция и прочие полезности -
https://github.com/makiuchi-d/sqlite-sharp/blob/master/SqliteSharp/Sqlite3.cs

Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
[DllImport(dllname, EntryPoint = "sqlite3_column_bytes")]
		static extern int sqlite3_column_bytes(IntPtr pStmt, int iCol);

		public static int ColumnBytes(IntPtr pStmt, int iCol)
		{
			return sqlite3_column_bytes(pStmt, iCol);
		}

		[DllImport(dllname, EntryPoint = "sqlite3_column_blob")]
		static extern IntPtr sqlite3_column_blob(IntPtr pStmt, int iCol);

		public static byte[] ColumnBlob(IntPtr pStmt, int iCol)
		{
			int size = ColumnBytes(pStmt, iCol);
			var pBlob = sqlite3_column_blob(pStmt, iCol);

			var data = new byte[size];
			Marshal.Copy(pBlob, data, 0, size);

			return data;
		}
...
Рейтинг: 0 / 0
Получить изображение неизвестного размера (байтовый массив) из dll C++ --> C#
    #39437661
Фотография Изопропил
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Arbit2. как очистить память выделенную под массив в коде dll (желательного без повторного вызова DLL)
не выделять память с-шным рантаймом(new, malloc и т д)

память, выделенная CoTaskMemAlloc/GlobaAlloc в c# легко управляется методами класса Marshal,
а зачастую можно и штатным маршаллингом обойтись (при передаче параметров-массивов можно указать направление передачи и в каком из параметров находится длина массива )
в MSDN всё описано
...
Рейтинг: 0 / 0
Получить изображение неизвестного размера (байтовый массив) из dll C++ --> C#
    #39438135
Arbit
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Изопропил, спасибо большое за помощь!

Если я правильно понял, то для получения картинки из базы придется 2 раза дергать dll из шарпа?
1 - получить размер массива,
2 - получить указатель на массив

Кроме того я не понял, как апишные функции импортируются в С# из dll если они находятся внутри другой функции,
в которую передаются параметры для селекта нужной картинки....?

Что-то в голове бардак по этому вопросу...
Не сочти за труд растолкуй пожалуйста "особоодаренному"
Извини что достаю, я итак стараюсь реже беспокоить
...
Рейтинг: 0 / 0
Получить изображение неизвестного размера (байтовый массив) из dll C++ --> C#
    #39438144
Arbit
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Изопропил , прости!

Я догнал, твой пример из ссылки которую ты дал.
Но мне нужно через свою dll , потому что в dll прежде чем прочитать или записать в базу с
данными происходят преобразования. А делать это в шарпе я не хочу.
...
Рейтинг: 0 / 0
Получить изображение неизвестного размера (байтовый массив) из dll C++ --> C#
    #39438150
Arbit
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
В догонку

Кроме того у меня нет отдельной dll sqlite. У меня все скомпилировано в единый проект моей dll
...
Рейтинг: 0 / 0
Получить изображение неизвестного размера (байтовый массив) из dll C++ --> C#
    #39438192
Фотография Изопропил
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ArbitВ догонку

Кроме того у меня нет отдельной dll sqlite. У меня все скомпилировано в единый проект моей dll
это не страшно

короче - возвращай из C - из сишного кода память выделенную CoTaskMemAlloc
принимай в с# как IntPtr,
Marshal.Copy - скопирует,
Marshal.FreeCoTaskMem - освободит(
...
Рейтинг: 0 / 0
Получить изображение неизвестного размера (байтовый массив) из dll C++ --> C#
    #39438275
Arbit
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Изопропилкороче - возвращай из C - из сишного кода память выделенную CoTaskMemAlloc
То есть все-таки дважды дергать dll + дважды обращаться к базе?
1 - в шарп получаю размер картинки
2 - в шарпе выделяю память CoTaskMemAlloc и передаю в dll указатель на нее и получаю картинку
и очищаю память Marshal.FreeCoTaskMem

Короче я попробовал еще такой вариант в одно обращение к dll (память выделяется в С++):

Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
[DllImport(@"D:\ProjectsC#\SQLite\Debug\base.dll")]
        public static extern IntPtr DLL_LoadImage(int KeyBinary, ref int ArrSize);

public static byte[] LoadImage(ref DataGridView dgv)
        {
            int KeyBinary = dgv.CurrentRow.Cells["KeyBinary"].Value.ToString();
            int ArrSize = 0;
            IntPtr pArrImg = DLL_LoadImage(KeyBinary, ref ArrSize);
            byte[] arrImg = new byte[ArrSize];

            Marshal.Copy(pArrImg, arrImg, 0, arrImg.Length););
            Marshal.FreeHGlobal(pArrImg);  //Освобождает память, выделенную ранее из неуправляемой памяти процесса.(MSDN)

            return arrImg;
        }


Но если я запускаю приложение из студии, то на строчке Marshal.FreeHGlobal(pArrImg) ;программа вылетает без всяких сообщений

А если я запускаю экзешник из папки, то программа работает шустро, но...
В Task Manager я вижу утечку памяти с каждой новой загрузкой картинки
То есть Marshal.FreeHGlobal(pArrImg) память не освобождает.

А ведь в MSDN написано:
Освобождает память, выделенную ранее из неуправляемой памяти процесса.(MSDN)
Почему так?

Кстати FreeCoTaskMem(IntPtr) - это для задач COM.
А в чем для моего случая разница между
FreeCoTaskMem(IntPtr) и FreeHGlobal(IntPtr)?

Что делать? Хочется в один клик

Посоветуй
...
Рейтинг: 0 / 0
Получить изображение неизвестного размера (байтовый массив) из dll C++ --> C#
    #39438302
Фотография Изопропил
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ArbitТо есть все-таки дважды дергать dll + дважды обращаться к базе?
1 - в шарп получаю размер картинки
2 - в шарпе выделяю память CoTaskMemAlloc и передаю в dll указатель на нее и получаю картинку
и очищаю память Marshal.FreeCoTaskMem
не так.

в Шарп сразу получаешь и размер и указатель (память сразу выделяется в сишной dll)
CoTaskMemAlloc - в сишном коде

а очищаешь память в Шарпе - одно обращение к внешней DLL


ArbitКстати FreeCoTaskMem(IntPtr) - это для задач COM.
на заборе куй написано, а там - дрова
для разных задач, активно используется для взаимодействия с неуправляемым кодом и COM-интеропа

ArbitА в чем для моего случая разница между
FreeCoTaskMem(IntPtr) и FreeHGlobal(IntPtr)?

разные пулы памяти. главное - один и тот же использовать для управления одним участком памяти
...
Рейтинг: 0 / 0
Получить изображение неизвестного размера (байтовый массив) из dll C++ --> C#
    #39438350
Arbit
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Изопропил, огромное спасибо!
ИзопропилCoTaskMemAlloc - в сишном коде
Вот оно ключевое слово!!!
Все работает!!!!

Изопропилне выделять память с-шным рантаймом(new, malloc и т д)
Это имеется ввиду только ситуация когда связка С++ и С# и память выеляется на стороне С++?
В чем тут причина?

Еще раз благодарю за помощь!
Гуру есть Гуру!
...
Рейтинг: 0 / 0
Получить изображение неизвестного размера (байтовый массив) из dll C++ --> C#
    #39438385
Фотография Изопропил
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ArbitЭто имеется ввиду только ситуация когда связка С++ и С# и память выеляется на стороне С++?
В чем тут причина?
это бывает и без c#

например,при взаимодействии dll, сделанных разными компиляторами или собранных со статически
прилинкованным рантаймом.
(у каждой dll может оказаться свой менеджер памяти)
...
Рейтинг: 0 / 0
Получить изображение неизвестного размера (байтовый массив) из dll C++ --> C#
    #39438864
Arbit
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Теперь полная ясность
Спасибо большое!
...
Рейтинг: 0 / 0
12 сообщений из 12, страница 1 из 1
Форумы / WinForms, .Net Framework [игнор отключен] [закрыт для гостей] / Получить изображение неизвестного размера (байтовый массив) из dll C++ --> C#
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]