информационная безопасность
без паники и всерьез
 подробно о проектеRambler's Top100
Портрет посетителяSpanning Tree Protocol: недокументированное применениеГде водятся OGRы
BugTraq.Ru
Русский BugTraq
 Анализ криптографических сетевых... 
 Модель надежности двухузлового... 
 Специальные марковские модели надежности... 
 Три миллиона электронных замков... 
 Doom на газонокосилках 
 Умер Никлаус Вирт 
главная обзор RSN блог библиотека закон бред форум dnet о проекте
bugtraq.ru / форум / programming
Имя Пароль
ФОРУМ
если вы видите этот текст, отключите в настройках форума использование JavaScript
регистрация





Легенда:
  новое сообщение
  закрытая нитка
  новое сообщение
  в закрытой нитке
  старое сообщение
  • Напоминаю, что масса вопросов по функционированию форума снимается после прочтения его описания.
  • Новичкам также крайне полезно ознакомиться с данным документом.
Лишняя операция - боксинг/анбоксинг (или по умному маршалинг/анмаршалинг) - обычное дело в дот НЕТ 08.06.09 03:20  Число просмотров: 3822
Автор: void <Grebnev Valery> Статус: Elderman
<"чистая" ссылка>
<programming>
[C++] Вызов C++ из C# 04.06.09 18:18  
Автор: PS <PS> Статус: Elderman
<"чистая" ссылка>
Есть dll на C++, в ней функция, которую вызываю из C#
Получаю маленькую фигню с указателями.

Итак, в dll (C++) определена структура и ф-ия:
// Просто определяем структуру
class ST
{
public:
	char* ptr;
	int t;
};

DLLFORSHARP_API int Test(ST& st, char* ptr )
{
	ofstream of;
	of.open( "c:/testdll.txt" );

       // Выводим в файл указатель переданый в структуре, и указатель, переданый в стеке.
	stringstream ss2;
	ss2 << hex << (int)st.ptr << " " << (int)ptr;
	of << ss2.str().c_str() << endl;

       // Выводим строчку из структуры
	string s( st.ptr );	
	of << s.c_str() << endl;

        // Выводим строчку из стека
	string s2( ptr );	
	of << s2.c_str() << endl;

       // Для проверки выводим число
	stringstream ss;
	ss << st.t;
	of << ss.str().c_str();
	of.close();
	
	return s.size();
}

---

В тестовой програме на C# написан следующий код:
    struct ST
    {
        public byte[] ptr;
        public int t;
    };

    class Program
    {
        [DllImport("dllForSharp.dll")]
        public static extern int Test(ref ST param, byte[] param2);

        static void Main(string[] args)
        {
            string test = "kuku";
            ST st;
            st.ptr = System.Text.ASCIIEncoding.Default.GetBytes(test);
            st.t = 105;            

            // В структуре, и во втором параметре у нас один и тот же "указатель"
            Test(ref st, st.ptr);
        }

---

И получаем такой вот результат:
12c9ac0 15776c0

kuku
105

1. Число вывелось верно - структура передалась верно (ничего не съехало, байтики в нужной последовательности)
2. Строка kuku, переданая во втором параметре вывелась верно - byte[] вполне валидно можно рассматривать как сишный char*

3. Внимание вопрос: как оказалось, что st.ptr в структуре отлично от st.ptr во втором параметре ???
Внутри структуры это 12c9ac0, в в параметре 15776c0. Хотя передавал одно и то же:

st.ptr = System.Text.ASCIIEncoding.Default.GetBytes(test);
Test(ref st, st.ptr);

Пока никаких идей.
Двойное разименование указателя при вызове функции Test? 15.06.09 01:40  
Автор: Den <Denis> Статус: The Elderman
Отредактировано 15.06.09 01:44  Количество правок: 1
<"чистая" ссылка>
Во втором параметре передаешь указатель на указатель?
Почему указатель на указатель ??? 15.06.09 11:33  
Автор: PS <PS> Статус: Elderman
<"чистая" ссылка>
> Во втором параметре передаешь указатель на указатель?

class ST
{
public:
char* ptr;
...

DLLFORSHARP_API int Test(ST& st, char* ptr )
...

struct ST
{
public byte[] ptr;
...
public static extern int Test(ref ST param, byte[] param2);
...
ST st;
...
Test(ref st, st.ptr);
...

В C++ коде определяю char* ptr, в C# коде, аналогично, byte[] ptr.
Где здесь указатель на указатель в упор не вижу.
[C++] Возможно сборщик балуется 04.06.09 21:44  
Автор: amirul <Serge> Статус: The Elderman
Отредактировано 04.06.09 21:46  Количество правок: 1
<"чистая" ссылка>
> 3. Внимание вопрос: как оказалось, что st.ptr в структуре
> отлично от st.ptr во втором параметре ???
> Внутри структуры это 12c9ac0, в в параметре 15776c0. Хотя
> передавал одно и то же:

Насколько я помню у дотнета перемещающий GC (http://en.wikipedia.org/wiki/Generational_GC#Moving_vs._non-moving) и соответственно "указатель" на объект многократно меняется по ходу выполнения программы. В MC++ есть pin_ptr, который запрещает перемещать данный объект. В шарпе для этих целей есть fixed http://msdn.microsoft.com/en-us/library/f58wzh21(VS.80).aspx
Решение найдено 05.06.09 12:18  
Автор: PS <PS> Статус: Elderman
Отредактировано 05.06.09 12:25  Количество правок: 2
<"чистая" ссылка>
> Насколько я помню у дотнета перемещающий GC
> (http://en.wikipedia.org/wiki/Generational_GC#Moving_vs._no
> n-moving) и соответственно "указатель" на объект
> многократно меняется по ходу выполнения программы. В MC++
> есть pin_ptr, который запрещает перемещать данный объект. В
> шарпе для этих целей есть fixed
> http://msdn.microsoft.com/en-us/library/f58wzh21(VS.80).asp
> x

Идея задачи была такой: не использовать unsafe код, и в то же время дергать dll с указателями.
Получилось вот такое:
    struct ST
    {        
        public IntPtr ptr;
        public int t;
    };

    class Program
    {
        [DllImport("dllForSharp.dll")]
        public static extern int Test(ref ST param, IntPtr param2);

        static void Main(string[] args)
        {
            string test = "kuku";            
            byte[] b = System.Text.ASCIIEncoding.Default.GetBytes(test);                       

            ST st;
            st.ptr = Marshal.UnsafeAddrOfPinnedArrayElement(b, 0);
            st.t = 105;

            Test(ref st, st.ptr);            
        }

---

Разницы между первоначальным не работающим вариантом и этим:
1. byte[] заменен на IntPtr
2. Появилась "лишняя" операция
Marshal.UnsafeAddrOfPinnedArrayElement(b, 0);
Лишняя операция - боксинг/анбоксинг (или по умному маршалинг/анмаршалинг) - обычное дело в дот НЕТ 08.06.09 03:20  
Автор: void <Grebnev Valery> Статус: Elderman
<"чистая" ссылка>
COM / DCOM? 08.06.09 21:34  
Автор: Den <Denis> Статус: The Elderman
<"чистая" ссылка>
Да, все понятно, но что конкретно... 08.06.09 13:00  
Автор: PS <PS> Статус: Elderman
<"чистая" ссылка>
Решение задачи то найдено, но вопрос все равно остался - почему byte[] в стеке передается нормально, как указатель на область данных, а тот же byte[] в структуре - уже имеет совсем другое значение ?

Идея о GC мне кажется не совсем верной. Если бы она была верной, то сценарий был бы таким:
1. записали в стек один указатель
2. gc поменял адрес
3. записали в стек другой указатель
4. вызвали функцию
Таким образом вызывая функцию два раза подряд мы бы получили 4ре разных указателя.
Однако, по моим тестам видно, что указатель передающийся в структуре всегда один и тот же, и всегда отличный от указателя передающегося в параметре функции. Например, по первому вызову 12c9ac0, 15776c0, а при втором 12c9ac0, 15776f4.
Т.ч. gc, конечно меняет местоположение массива, но описанная проблема в чем то другом.
Такое впечатление что
F( byte[] ptr ) и struct S { byte[] ptr } - имеют различное внутреннее представление ptr, который указывает на одну и ту же область памяти. Видимо .net различает что есть что и "приводит" разные цифры в ptr к "одному знаменателю".
Это лишь предположение. Литературу по .net типа "windows" Рихтера мне найти еще не удалось.
1




Rambler's Top100
Рейтинг@Mail.ru


  Copyright © 2001-2024 Dmitry Leonov   Page build time: 0 s   Design: Vadim Derkach