Легенда:
новое сообщение
закрытая нитка
новое сообщение
в закрытой нитке
старое сообщение
|
- Напоминаю, что масса вопросов по функционированию форума снимается после прочтения его описания.
- Новичкам также крайне полезно ознакомиться с данным документом.
[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 <Денис Т.> Статус: 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 <Денис Т.> Статус: 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" Рихтера мне найти еще не удалось.
|
|
|