powered by simpleCommunicator - 2.0.59     © 2025 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / C++ [игнор отключен] [закрыт для гостей] / Передача данных C# -> DLL С++ ->SQLite и обратно
58 сообщений из 58, показаны все 3 страниц
Передача данных C# -> DLL С++ ->SQLite и обратно
    #39403049
Arbit
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Здравствуйте уважаемые Гуру!

Сразу прошу вас не пинать больно, так как я новичок
Собственно не могу сообразить как передать в C#, полученный в dll на c++
набор записей из SQLite.

Использовать NET System.Data.SQLite для работы пожалуйста не предлагайте.

C# используется только для пользовательского интерфейса, а вся работа с базой (запросы)
осуществляется только в DLL на с++.

Параметры для DLL я передаю из C# и обратно строковые данные тоже могу получить.
А вот как можно передать из dll результирующий набор записей в C# (в виде объекта)
на подобии DataTable в .NET чтобы присвоить как sourse DataGridView (если таковое возможно)?

Или заполнять Grid построчно, но опять таки нужен полученные из dll объект (набор строк)

Направьте пожалуйста мысль в правильную сторону. Мое гугление пока без нужного результата.
Можно ли это сделать Маршалингом, если да, то подскажите как.
С маршалингом простых данных я разобрался.
А вот как со сложными структурами или объектами...?
Как их подготовить в С++ к передаче и в С# распаковать не могу понять.

Еще была мысль использовать JSON и передавать одной строкой.
Распаковать строку JSON в объект С# я распакую, а вот как запаковать объект
(набор записей) в строку JSON на стороне dll не нашел.
Библиотеки json для с# и С++ в наличии.
Вопрос корости работы такой связки пока не очень критичен, но желательно иметь в виду.

Может есть другие решения, если приведете кусочек кода буду счастлив безмерно!
Заранее благодарен откликнувшимся.
...
Рейтинг: 0 / 0
Передача данных C# -> DLL С++ ->SQLite и обратно
    #39403061
Фотография Изопропил
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ArbitА вот как со сложными структурами или объектами...?
можно передать в c# XML, пригодный для прямой десериализации в dataset
Модератор: Отредактировано
...
Рейтинг: 0 / 0
Передача данных C# -> DLL С++ ->SQLite и обратно
    #39403075
Arbit
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Изопропил, безмерно рад общению! :)

а "анально" - это как перевести?
Это как - "банально" или это как - через " *опу" :) Я шучу, просто рад встрече

А что лучше использовать в моем случае с точки зрения производительности, XML или jcon?
Я так понял что если - XML, то можно подключить как source к гриду,
а если - json, то только заполнить грид строками в цикле из объекта после распаковки json?
По скорости это не будет иметь значения?
...
Рейтинг: 0 / 0
Передача данных C# -> DLL С++ ->SQLite и обратно
    #39403079
Siemargl
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
>Направьте пожалуйста мысль в правильную сторону

1. Читать учебники

2. Пока достаточно не прочитал, использовать стандартные средства работы с СУБД из C#

3. Не писать в С++ топик без оснований
...
Рейтинг: 0 / 0
Передача данных C# -> DLL С++ ->SQLite и обратно
    #39403110
Arbit
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Изопропил, спасибо большое!
Как всегда, кратко и исчерпывающе!
Именно то что мне нужно.
...
Рейтинг: 0 / 0
Передача данных C# -> DLL С++ ->SQLite и обратно
    #39405089
Arbit
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Изопропил, доброго дня!

Изопропил можно передать в c# XML, пригодный для прямой десериализации в dataset
А можно сериализовать/десериализовать объект DataTable без помещения его предварительно в контейнер DataSet?
Я обычно сразу загружаю вот так, если всего одна таблица:
Код: c#
1.
2.
3.
var adapter = new OleDbDataAdapter(cmd);
var dataTable = new DataTable();
adapter.Fill(dataTable)


или без DataSet это не работает?
...
Рейтинг: 0 / 0
Передача данных C# -> DLL С++ ->SQLite и обратно
    #39405310
Arbit
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Изопропил, Спасибо большое!!!
Все работает великолепно.
...
Рейтинг: 0 / 0
Передача данных C# -> DLL С++ ->SQLite и обратно
    #39512497
Arbit
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Изопропил, Прошу заранее прощения за беспокойство!

Использовал XML для передачи набора строк из SQLite и все было хорошо, в DataTable все загружалось!
Любые данные!
Но это работало на очень маленьких наборах строк

Когда же понадобилось передать из С++ в С# данные из более чем 33-34 строк(в зависимости от количества полей)
Получаю пустой DataTable.

Это что, недостаточно памяти выделяется для DataTable?
Подскажите пожалуйста как можно решить эту задачу.
Может я не учел чего-то формируя XML в С++?
Или неправильно принимаю XML в С#?

Заранее благодарен за помощь!
...
Рейтинг: 0 / 0
Передача данных C# -> DLL С++ ->SQLite и обратно
    #39512503
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Arbit, ты в ГитХабе есть?
...
Рейтинг: 0 / 0
Передача данных C# -> DLL С++ ->SQLite и обратно
    #39512508
Arbit
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Siemargl,

Еще раз повторюсь.
Код рабочий. Данные любые отправляются и принимаются!!!
Проблема только в том, что если набор строк превышает предел (у меня это - 33 строки)
сериализованная строка не принимается из DLL Получаю исключение:
{"Attempted to read or write protected memory. This is often an indication that other memory is corrupt."}
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
public static bool Select(string QueryName, ref DataTable dt, string WhereValues="")
        {
            //Вызываем библиотечную функцию (в параметре - имя запроса)
            try
            {
                string strXML = DLL_Select(QueryName, WhereValues, ref CountRows);
                //Десериализуем полученные данные
                strXML = Main.Base64DecodeString(strXML);
                //Заполняем DataTable полученными данными
                using(StringReader rd = new StringReader(strXML))
                {
                    dt = new DataTable();
                    dt.ReadXml(rd);
                    rd.Dispose();
                }
            }
            catch
            {
                return false;
            }
            
            return true;
        }
...
Рейтинг: 0 / 0
Передача данных C# -> DLL С++ ->SQLite и обратно
    #39512509
Arbit
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
mayton,
откуда мне там быть? :))
Я не профи, я просто люблю программирование
...
Рейтинг: 0 / 0
Передача данных C# -> DLL С++ ->SQLite и обратно
    #39512571
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Туда не нужен пропуск профи.
...
Рейтинг: 0 / 0
Передача данных C# -> DLL С++ ->SQLite и обратно
    #39512933
Siemargl
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Модератор: Отредактировано
Нужен код DLL_Select - в ней не выделяется достаточно памяти
...
Рейтинг: 0 / 0
Передача данных C# -> DLL С++ ->SQLite и обратно
    #39512938
Arbit
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Siemargl,
Да я понял что мало памяти.
В dll формирование XML строки проверил - все правильно
Сейчас сам попробую найти косяк с памятью.
Если не получится то побеспокою Вас

Спасибо за желание помочь
...
Рейтинг: 0 / 0
Передача данных C# -> DLL С++ ->SQLite и обратно
    #39512960
Arbit
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Siemargl,

Я делал так:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
extern "C" __declspec(dllexport) BSTR DLL_Select(const char* pQueryName, const char* pWhereValues, int  *CountRow)
{
        //Генерирую strXML (c этим все в порядке, строка правильная)
        //Перевожу ее в base64 и возвращаю:

	return _bstr_t(strXML.c_str());
}



В 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.
[DllImport(@"D:\ProjectsC#\FinStudio\Debug\FinStudioDLL.dll")]
        [return: MarshalAs(UnmanagedType.BStr)]
        public static extern string DLL_Select(string QueryName, string WhereValues, ref int CountRows);

public static bool Select(string QueryName, ref DataTable dt, string WhereValues="")
        {
            //Вызываем библиотечную функцию (в параметре - имя запроса)
            try
            {
                string strXML = DLL_Select(QueryName, WhereValues, ref CountRows);
                //Десериализуем полученные данные
                strXML = Main.Base64DecodeString(strXML);
                //Заполняем DataTable полученными данными
                using(StringReader rd = new StringReader(strXML))
                {
                    dt.ReadXml(rd);
                    rd.Dispose();
                }
            }
            catch
            {
                return false;
            }
            
            return true;
        }


У меня есть подозрение, что в таком исполнении передачи строки, в памяти выделяется какой-то default размер
И все, что превышает - лезет в защищенную память.
Видимо нужно передавать строку, как байтовый массив и возвращать указатель на этот массив и размер его.
А в С# получать указатель как IntPtr и переводить массив в string
Или есть более правильное решение?
...
Рейтинг: 0 / 0
Передача данных C# -> DLL С++ ->SQLite и обратно
    #39512967
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Arbit//Перевожу ее в base64 и возвращаю:

И возвращаешь указатель на уже освобождённую память.
Модератор: Отредактировано
...
Рейтинг: 0 / 0
Передача данных C# -> DLL С++ ->SQLite и обратно
    #39512979
Arbit
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Dimitry Sibiryakov,
А нельзя ли чуть полегче, без цитат
И чуть подробнее

Я не профи и не студент, и вообще не технарь. Я из другого "цеха" я программирую мозги на любой "платформе".
А сейчас изучаю другое программирование и по ходу пишу свой маленький проектик.
Давайте дружить! :)

Приведенный код работает, но до определенного объема передаваемых данных
Если можете пролить свет, буду благодарен
...
Рейтинг: 0 / 0
Передача данных C# -> DLL С++ ->SQLite и обратно
    #39513001
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ArbitЯ не профи и не студент, и вообще не технарь. Я из другого "цеха" я программирую мозги на
любой "платформе".

Ок, перевожу на лекарский: ты посылаешь сестру за пациентом с койки номер шесть. Но ты не
позаботился о том, чтобы этого пациента не трогали, поэтому он давно умер, был вскрыт,
расфасован на органы и частично кремирован. То, что тебе притащит сестра может быть куском
нужного пациента, а может быть и вообще левым пациентом, которому не повезло занять эту
койку гораздо позже. Если не повезёт, то там вообще не окажется этой койки, поскольку она
сгорела вместе с госпиталем.

А теперь таки начни изучать что такое компьютеры, как они работают, что такое память и как
ею следует управлять с тем, чтобы и койка была на месте и пациента не порезали до момента
как его к тебе привезут.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Передача данных C# -> DLL С++ ->SQLite и обратно
    #39513011
Arbit
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Dimitry Sibiryakov,
Да...
А я к Вам ведь, батенька, на ВЫ,
И больше чем уверен, что вдвое если не больше старше Вас..

А ведь некоторое время назад я получил от Вас достаточно приличную для меня помощь
и, причем, без всяких понтов.
Я даже прилюдно выразил свою Особую благодарность Вам
и другим Вашим коллегам

Если бы у Уважаемого Изопропила была минутка свободного времени, он бы не писал так много букв,
Одно предложение - и решение вопроса было бы найдено. Достойный пример для подражания!

Ну да ладно, бог Вам судья
На этом закончим общение
...
Рейтинг: 0 / 0
Передача данных C# -> DLL С++ ->SQLite и обратно
    #39513036
Siemargl
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Arbit..И больше чем уверен, что вдвое если не больше старше Вас..Эт врядли, столько пока не живут=)

В общем проблема в том, что твой strXML.c_str() уничтожен по выходу из функции, как локальная переменная.

Лучше передавай функции свой буфер нужного (с запасом размера), в который будет писаться результат.

С bstr тоже можно, но контролировать кто создает и освобождает ее память
...
Рейтинг: 0 / 0
Передача данных C# -> DLL С++ ->SQLite и обратно
    #39513039
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Arbit, не переживай док! Поможем тебе. А все нехорожие и злые поциенты
будут прокапаны и проклизьмены и уложены спать.
...
Рейтинг: 0 / 0
Передача данных C# -> DLL С++ ->SQLite и обратно
    #39513042
Siemargl
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SiemarglЛучше передавай функции свой буфер нужного (с запасом размера), в который будет писаться результат.
Пока помню, еще его надо залочить в памяти,чтобы GC не передвинул. Все в MSDN есть
...
Рейтинг: 0 / 0
Передача данных C# -> DLL С++ ->SQLite и обратно
    #39513079
Arbit
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Siemargl,

SiemarglВ общем проблема в том, что твой strXML.c_str() уничтожен по выходу из функции, как локальная переменная.
Объясните пожалуйста "особоодаренному" почему:
не смотря на это я получаю в С# XML строку десериализую ее и гружу благополучно в grid?
Проблема только в том что при передаче строки длиной больше определенного значения вылетает исключение

Есть у меня еще вариант. Я передавал из 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.
[DllImport(@"D:\ProjectsC#\FinStudio\Debug\FinStudio.dll")]
        public static extern IntPtr DLL_LoadImage(string pKeyBinary, ref int ArrSize);  

IntPtr pArrImg = DLL_LoadImage(KeyBinary, ref ArrSize);

        public static byte[] LoadImage(ref DataGridView dgv)
        {
            string KeyBinary = dgv.CurrentRow.Cells["KeyBinary"].Value.ToString();
            int ArrSize = 0;
            IntPtr pArrImg = DLL_LoadImage(KeyBinary, ref ArrSize);
            byte[] arrImg = new byte[ArrSize];
            try
            {
                Marshal.Copy(pArrImg, arrImg, 0, arrImg.Length);
            }
            catch
            {
                ...
            }
            finally
            {
                Marshal.FreeCoTaskMem(pArrImg);
            }

            return arrImg;
        }


В C++
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
extern "C" __declspec(dllexport) byte* DLL_LoadImage(const char* pKeyBinary, int *psize)
{
byte* pBuff; //Сюда грузил изображение

*psize  //размер буфера

	return  pBuff;
}


Можно пойти этим путем при передачи строки, но
теперь нужно перегнать string в байтовый массив и как быть с символом конца строки?
записывать его в массив или нет для передачи из DLL в С#?
И как лучше сделать это преобразование?

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

Что подскажите?

Спасибо!
...
Рейтинг: 0 / 0
Передача данных C# -> DLL С++ ->SQLite и обратно
    #39513103
YuRock
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ArbitОбъясните пожалуйста "особоодаренному" почему:
не смотря на это я получаю в С# XML строку десериализую ее и гружу благополучно в grid?
Проблема только в том что при передаче строки длиной больше определенного значения вылетает исключение
Тебе Сибиряков именно на этот вопрос и ответил, только на своем языке.
Ладно, переведу:
Освобожденная память локального объекта, в которой была полная правильная строка xml, все еще может полностью или частично принадлежать твоему процессу, и если повезет - даже с правильными не затертыми данными.
На маленьких размерах тебе везет (хотя дело не в везении, конечно, а в том, что менеджер памяти резервный буфер оставил в этом месте, плюс другие потоки не пишут (пока) туда).
Медсестра принесла часть трупа))

Сделай, например, так:
1. Выдели вручную память (под строку) в dll под эту строку (xml.c_str), скопируй в нее данные, ее и возвращай в c#
2. Сделай в dll функцию cpp_free с параметром - указатель на строку, в функции просто удаляй память
3. В c# после использования строки вызови cpp_free

Думаю, должно заработать, если шарп "не испортит (не передвинет) указатель", но тут я уже не разбираюсь.
...
Рейтинг: 0 / 0
Передача данных C# -> DLL С++ ->SQLite и обратно
    #39513349
Arbit
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
YuRock, спасибо большое
YuRockОсвобожденная память локального объекта, в которой была полная правильная строка xml, все еще может полностью или частично принадлежать твоему процессу, и если повезет - даже с правильными не затертыми данными .
Все кратко и понятно!
Разве трудно было написать Сибирякову эти две строчи? Ан нет... ладно проехали
YuRock2. Сделай в dll функцию cpp_free с параметром - указатель на строку, в функции просто удаляй память
3. В c# после использования строки вызови cpp_free
Мне не хочется дважды обращаться к DLL - второй раз для очистки памяти.
Хочется за один раз
а если я сделаю как писал выше
C#
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
            IntPtr pArrImg = DLL_LoadImage(KeyBinary, ref ArrSize);
            byte[] arrImg = new byte[ArrSize];
            try
            {
                Marshal.Copy(pArrImg, arrImg, 0, arrImg.Length);
            }
            catch
            {
                ...
            }
            finally
            {
                Marshal.FreeCoTaskMem(pArrImg); //Освобожу память здесь по полученному указателю из DLL - это будет правильно??? 
            }



Спасибо.
...
Рейтинг: 0 / 0
Передача данных C# -> DLL С++ ->SQLite и обратно
    #39513376
Dimitry Sibiryakov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ArbitОсвобожу память здесь по полученному указателю из DLL - это будет правильно???

Способ выделения памяти должен соответствовать способу её освобождения. Нельзя пришивать
руку на место ноги.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
Передача данных C# -> DLL С++ ->SQLite и обратно
    #39513381
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Arbitа если я сделаю как писал выше
C#
Код: c#
1.
2.
3.
            IntPtr pArrImg = DLL_LoadImage(KeyBinary, ref ArrSize);
                ...
                Marshal.FreeCoTaskMem(pArrImg); //Освобожу память здесь по полученному указателю из DLL - это будет правильно??? 


Нельзя так делать, потому что разные менеджеры памяти по разному работают, если по-простому объяснять, то память не выделяется каждый раз, а просто выдается кусок ранее выделенной и делается отметка что кусок занят. Эти отметки разные менеджеры памяти делают по-разному.
Поэтому освобождать память надо теми же средствами что и выделять, т.е. если выделил ее malloc() в С++, то и освободить надо вызовом free() в C++.

Проще всего сделать как YuRock предложил, т.е. добавить в DLL функцию
Код: plaintext
1.
2.
3.
extern "C" __declspec(dllexport) void DLL_FreeMemory(byte* data) {
   free(data);
}


И ее вызвать из C#
Код: c#
1.
2.
3.
            IntPtr pArrImg = DLL_LoadImage(KeyBinary, ref ArrSize);
                ...
            DLL_FreeMemory(pArrImg);
...
Рейтинг: 0 / 0
Передача данных C# -> DLL С++ ->SQLite и обратно
    #39513523
Arbit
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Всем большое большое спасибо все понятно!

Последний вопрос:
В DLL мне надо string перевести в массив, на который я передаю указатель.
1. какой массив лучше принять в С# - байтовый или char?
2. как быть с символом конца строки - в DLL его записывать в массив или нет?

в C# массив ведь нужно будет снова преобразовывать в строку.
Как это правильно сделать?

В общем у меня все вопросы сейчас крутятся вокруг темы обмена различными
данными между managed и unmanaged кодом

Спасибо
...
Рейтинг: 0 / 0
Передача данных C# -> DLL С++ ->SQLite и обратно
    #39513533
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
string в С++ и C# разные вещи, первый в ANSI кодировках, второй с юникоде, поэтому лучше в C# принимать как массив байт, а затем конвертировать в строку.
Код: plaintext
1.
2.
var encoder = Encoding.GetEncoding(1251);
string result = encoder.GetString(Array, ...);


По поводу нуля: он не нужен, если надо только записать для последующего чтения в C#
...
Рейтинг: 0 / 0
Передача данных C# -> DLL С++ ->SQLite и обратно
    #39513557
Фотография Изопропил
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Arbit1. какой массив лучше принять в С# - байтовый или char?
2. как быть с символом конца строки - в DLL его записывать в массив или нет?
лучше сразу char(wchar_t, юникод UTF-16) использовать)
нулевой терминатор - записывать.
...
Рейтинг: 0 / 0
Передача данных C# -> DLL С++ ->SQLite и обратно
    #39513564
YuRock
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Arbitа если я сделаю как писал выше
C#
Код: c#
1.
2.
Marshal.Copy(pArrImg, arrImg, 0, arrImg.Length);
Marshal.FreeCoTaskMem(pArrImg);



Я тут ничего не понимаю, увы.
Но что могу сказать: ты из C# заранее не знаешь и знать не можешь, сколько тебе необходимо памяти выделить. Ну можно, конечно, с запасом полтора гига выделят каждый раз, но это не вариант)

ArbitМне не хочется дважды обращаться к DLL - второй раз для очистки памяти.
Обращаешься ты один раз - при загрузке библиотеки. Далее ты просто вызываешь функции, которые уже ничем не отличаются от функций твоей программы.

Впрочем, как хочешь.
...
Рейтинг: 0 / 0
Передача данных C# -> DLL С++ ->SQLite и обратно
    #39513568
Фотография Изопропил
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
если выделять память под строку через ::SysAllocString

и принимать как BSTR - никакого дополнительного кода не нужно, маршаллер сам справится
...
Рейтинг: 0 / 0
Передача данных C# -> DLL С++ ->SQLite и обратно
    #39513614
Фотография Изопропил
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Код: plaintext
1.
2.
3.
4.
5.
extern "C" __declspec(dllexport) BSTR __stdcall DLL_Strings(BSTR * p,LPCWSTR p2) {
	::SysFreeString(*p);
	*p = ::SysAllocString(L"second вторая");
	return  ::SysAllocString(p2);
}


Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
[DllImport(@"Win32Project1.dll",CallingConvention= CallingConvention.StdCall)]
        [return: MarshalAs(UnmanagedType.BStr)]
        public static extern string DLL_Strings([MarshalAs(UnmanagedType.BStr)]ref string p, [MarshalAs(UnmanagedType.LPWStr),In]string p2);

....
       
string a =   "ячс";
string r = DLL_Strings(ref a,"фыва");
       
...
Рейтинг: 0 / 0
Передача данных C# -> DLL С++ ->SQLite и обратно
    #39513667
Arbit
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Изопропил, Сегодня мне счастье привалило, рад видеть! :)
Читаю последний Ваш пост и в голове нестыковка по вопросу очистки памяти.
Если я правильно понял, то очистка памяти в Вашем примере происходит не
в том коде, в котором она выделялась
Код: plaintext
1.
2.
3.
4.
5.
extern "C" __declspec(dllexport) BSTR __stdcall DLL_Strings(BSTR * p,LPCWSTR p2) {
	::SysFreeString(*p);
	*p = ::SysAllocString(L"second вторая");
	return  ::SysAllocString(p2);
}


Dimitry Sibiryakov и Дима Т в один голос говорят, что нужно чистить память там где она выделалась

Ранее мы с Вами разбирали этот вопрос
Изопропилкороче - возвращай из C - из сишного кода память выделенную CoTaskMemAlloc
принимай в с# как IntPtr,
Marshal.Copy - скопирует,
Marshal.FreeCoTaskMem - освободит
У меня это все работало и передавались данные (изображения) и нигде память не затиралась
Говорят что мне просто везло
Где-то я что-то напутал наверное.
Проясните пожалуйста
...
Рейтинг: 0 / 0
Передача данных C# -> DLL С++ ->SQLite и обратно
    #39513669
Arbit
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
YuRock,
YuRockНо что могу сказать: ты из C# заранее не знаешь и знать не можешь, сколько тебе необходимо памяти выделить. Ну можно, конечно, с запасом полтора гига выделят каждый раз, но это не вариант)
Не, память я выделяю в DLL и возвращаю в С# указатель на массив и его размер в параметре
...
Рейтинг: 0 / 0
Передача данных C# -> DLL С++ ->SQLite и обратно
    #39513674
Фотография Изопропил
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ArbitDimitry Sibiryakov и Дима Т в один голос говорят, что нужно чистить память там где она выделалась
это может упростить жизнь.

Но если мы знаем, как память выделялась и как работает маршаллер(или вручную маршаллинг делаем)
можно позволить себе выделять в одном месте, а освобождать в другом.
главное чтоб единые распределители памяти использовались(CoTaskMemAlloc-CoTaskMemFree,
SysAllocString-SysFreeString,GlobalAlloc-GlobalFree) ну а если случилось выделение malloc или new -
только так, где выделяли освобождать следует.


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

авторArbit
1. какой массив лучше принять в С# - байтовый или char?
2. как быть с символом конца строки - в DLL его записывать в массив или нет?

Изопропиллучше сразу char(wchar_t, юникод UTF-16) использовать)
нулевой терминатор - записывать.
Я сейчас передаю не короткие строки, а
сериализованную XML строку с данными из базы для передачи их в DataTable
Таблица в XML содержит 200-300 строк
Такую большую XML строку тоже лучше передавать как массив char?
...
Рейтинг: 0 / 0
Передача данных C# -> DLL С++ ->SQLite и обратно
    #39513680
Фотография Изопропил
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ArbitТакую большую XML строку тоже лучше передавать как массив char?ну она не такая уж и большая. я бы string передал (и длину передавать не придётся) и в utf-16 сразу бы перекодировал
...
Рейтинг: 0 / 0
Передача данных C# -> DLL С++ ->SQLite и обратно
    #39513681
Dima T
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ArbitИзопропил,

авторArbit
1. какой массив лучше принять в С# - байтовый или char?
2. как быть с символом конца строки - в DLL его записывать в массив или нет?

пропущено...
.
Я сейчас передаю не короткие строки, а
сериализованную XML строку с данными из базы для передачи их в DataTable
Таблица в XML содержит 200-300 строк
Такую большую XML строку тоже лучше передавать как массив char?
Прикинь в байтах: 200-300 строк даже если каждая 1 Кб, это всего 0.2-0.3 Мб, ниочем. Передавай как передастся и не заморачивайся.
...
Рейтинг: 0 / 0
Передача данных C# -> DLL С++ ->SQLite и обратно
    #39513684
Arbit
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
ИзопропилArbitDimitry Sibiryakov и Дима Т в один голос говорят, что нужно чистить память там где она выделалась
это может упростить жизнь.

Но если мы знаем, как память выделялась и как работает маршаллер(или вручную маршаллинг делаем)
можно позволить себе выделять в одном месте, а освобождать в другом.
главное чтоб единые распределители памяти использовались(CoTaskMemAlloc-CoTaskMemFree,
SysAllocString-SysFreeString,GlobalAlloc-GlobalFree
) ну а если случилось выделение malloc или new -
только так, где выделяли освобождать следует.

Например, массив, передаваемый по ссылке(ref) из c# кода маршаллером копируется в память, выделенную
CoTaskMemAlloc. C-код в dll имеет полное право сделать CoTaskMemFree и CoTaskMemAlloc.
а если строки передавались в массиве структур - то перед освобождением массива нужно ещё для строк сделать SysFreeString
Вот она - Квинтэссенция!!!
Огромное спасибо!
...
Рейтинг: 0 / 0
Передача данных C# -> DLL С++ ->SQLite и обратно
    #39513686
Arbit
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Dima T, Спасибо!
...
Рейтинг: 0 / 0
Передача данных C# -> DLL С++ ->SQLite и обратно
    #39513688
Arbit
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
ИзопропилArbitТакую большую XML строку тоже лучше передавать как массив char?ну она не такая уж и большая. я бы string передал (и длину передавать не придётся) и в utf-16 сразу бы перекодировал
Спасибо!
...
Рейтинг: 0 / 0
Передача данных C# -> DLL С++ ->SQLite и обратно
    #39513690
Arbit
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Дорогие Гуру!
Всем премного благодарен за помощь и внимание!
Всем хорошего отдыха в грядущие выходные!


Пошел ваять
...
Рейтинг: 0 / 0
Передача данных C# -> DLL С++ ->SQLite и обратно
    #39513705
Фотография Изопропил
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Arbit,

примечание - максимум вспомогательного кода лучше иметь на одной стороне
...
Рейтинг: 0 / 0
Передача данных C# -> DLL С++ ->SQLite и обратно
    #39513706
Siemargl
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
как же скучно я живу....

а тут столько эмоций на нечетном байте =(
...
Рейтинг: 0 / 0
Передача данных C# -> DLL С++ ->SQLite и обратно
    #39513762
Arbit
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Изопропил,
А что подразумевается под вспомогательным кодом?
И на какой стороне его предпочтительнее иметь? С++ или С#?

Вообще у меня основной код в DLL - работа с базой, вся промежуточная обработка данных перед и после базы
В С# только код по работе с пользовательским интерфейсом ввод и отображение данных
Да, еще в С# есть код по работе с моим сервером в интернете, но я его тоже перенесу в DLL (пока до этого руки еще не дошли)

Спасибо за совет
...
Рейтинг: 0 / 0
Передача данных C# -> DLL С++ ->SQLite и обратно
    #39513803
Фотография Изопропил
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
вспомогательный код - например вот
Arbit
Код: c#
1.
2.
Marshal.Copy(pArrImg, arrImg, 0, arrImg.Length);
Marshal.FreeCoTaskMem(pArrImg);


имеет отношение к маршаллингу, но не к решаемой прикладной задаче
...
Рейтинг: 0 / 0
Передача данных C# -> DLL С++ ->SQLite и обратно
    #39513898
Arbit
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Изопропил,
Изопропилимеет отношение к маршаллингу, но не к решаемой прикладной задаче
Да, я учту это.
Спасибо большое
...
Рейтинг: 0 / 0
Передача данных C# -> DLL С++ ->SQLite и обратно
    #39514161
Arbit
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Изопропил,
В итоге у получился такой вариант
С++
Код: plaintext
1.
2.
3.
4.
5.
6.
extern "C" __declspec(dllexport) BSTR DLL_Select(const char* pQueryName, const char* pWhereValues, int  *CountRow)
{
string strXML  // это сериализованная base64 XML строка 
_bstr_t XML = _bstr_t(strXML.c_str());	
	return ::SysAllocString(XML);
}


С#
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
[DllImport(@"D:\ProjectsC#\FinStudio\Debug\FinStudioDLL.dll", CallingConvention = CallingConvention.Cdecl)]
        [return: MarshalAs(UnmanagedType.BStr)]
 public static extern string DLL_Select(string QueryName, string WhereValues, ref int CountRows);

public static bool Select(string QueryName, ref DataTable dt, string WhereValues="")
        {
                string strXML = DLL_Select(QueryName, WhereValues, ref CountRows); 
                strXML = Main.Base64DecodeString(strXML);
                using(StringReader rd = new StringReader(strXML))
                {
                    dt.ReadXml(rd);
                    rd.Dispose();
                }
            return true;
        }


Все работает, передаются любые объемы данных

Теперь по очистке выделенной памяти:
Память выделялась в С++ с помощью SysAllocString
В С# маршаллер передал BSTR в string strXML
А как теперь освободить память после заполнения DataTable?
Есть Marshal.FreeCoTaskMem, Marsha.lFreeHGlobal, Marshal.FreeBSTR
Но Marshal. SysFreeString не нашел
Может - в данном случае это Marshal. FreeBSTR ?

Или string strXML очистит сборщик мусора С#?

Спасибо.
...
Рейтинг: 0 / 0
Передача данных C# -> DLL С++ ->SQLite и обратно
    #39514189
Arbit
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Или маршаллер в данном случае уже сам позаботился об очистке памяти?
...
Рейтинг: 0 / 0
Передача данных C# -> DLL С++ ->SQLite и обратно
    #39514196
Фотография Изопропил
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ArbitИли маршаллер в данном случае уже сам позаботился об очистке памяти?
да
...
Рейтинг: 0 / 0
Передача данных C# -> DLL С++ ->SQLite и обратно
    #39514342
Siemargl
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ArbitИли маршаллер в данном случае уже сам позаботился об очистке памяти?
BSTR это OLE2, там все построено на счетчиках ссылок.

честно говоря, я бы поверил Изопропилу, но перепроверил позднее, мало ли что думает дНет по этому поводу.

только не маршаллер об этом заботится, а OLE подсистема, быть занудой
...
Рейтинг: 0 / 0
Передача данных C# -> DLL С++ ->SQLite и обратно
    #39514368
Фотография Изопропил
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Siemargl,

SysAllocString - внутри это CoTaskMemAlloc, никакого IUnknown и счётчиков ссылок

Не стоит обобщать. А дотнет хорошо знает COM.

Занудство не уместно- именно маршалер вызывает ole функции управления памятью,
Для функций управления памятью OLE никакого подсчёта ссылок не производится - подсчёт ссылок только для COM интерфейсов работает
...
Рейтинг: 0 / 0
Передача данных C# -> DLL С++ ->SQLite и обратно
    #39514386
Siemargl
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Изопропил,

Если так, то в коде 20764900 утечка, т.к. нет освобождения того, что выделялось SysAllocString
...
Рейтинг: 0 / 0
Передача данных C# -> DLL С++ ->SQLite и обратно
    #39514388
Фотография Изопропил
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Siemargl,

Маршаллер освобождает (вызывает SysFreeString). - на основании того, что возвращаемая строка - BSTR

Точно так же, как и древних VB и VBA с внешними функциями из dll
...
Рейтинг: 0 / 0
Передача данных C# -> DLL С++ ->SQLite и обратно
    #39514497
Arbit
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Безмерно благодарен всем за ликбез!!!
Я заполнил большую брешь в своих познаниях благодаря вашим постам

Пошел реализовывать все в проекте.
Но я обязательно вернусь

Может вы мне заранее подскажете что лучше почитать по теме
реализации в приложении интерпретации подпрограммы на собственном макро-языке
список всех лексем уже есть. Нужен свой парсер, я так понимаю.

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

сначала рассмотреть вопрос об интеграции готового интерпретатора(javascript,python,lua,vbs...)
если всё-таки нужен свой - «Книгу дракона» можно почитать
( https://www.ozon.ru/context/detail/id/3829076/ )

ну и классику изучать - Flex и Bison
...
Рейтинг: 0 / 0
Передача данных C# -> DLL С++ ->SQLite и обратно
    #39514501
Arbit
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Изопропил,
Буду читать про Дракона:))

Если коротко, то пользователь , при работе с приложением может писать в RichTextBox
настройки (инструкции) используя этот специфический простенький макроязык.
Приложение, читая этот набор инструкций должно его распарсить и вызвать последовательность
определенных функции, написанные мной на языке С++.
...
Рейтинг: 0 / 0
58 сообщений из 58, показаны все 3 страниц
Форумы / C++ [игнор отключен] [закрыт для гостей] / Передача данных C# -> DLL С++ ->SQLite и обратно
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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