powered by simpleCommunicator - 2.0.36     © 2025 Programmizd 02
Форумы / WinForms, .Net Framework [игнор отключен] [закрыт для гостей] / Как получить фактический адрес делегата?
12 сообщений из 12, страница 1 из 1
Как получить фактический адрес делегата?
    #40067425
iskatelsql
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Есть замечательная статья, как можно использовать делегаты в качестве "callback"

https://docs.microsoft.com/ru-ru/dotnet/framework/interop/marshaling-a-delegate-as-a-callback-method

Но я так и не смог нагуглить, как получить адрес этого делегата, в смысле те циферки, что он передает функции.

Гуру, поделитесь Силой
...
Рейтинг: 0 / 0
Как получить фактический адрес делегата?
    #40067449
Сон Веры Павловны
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
iskatelsql
Но я так и не смог нагуглить, как получить адрес этого делегата, в смысле те циферки, что он передает функции.Гуру, поделитесь Силой

Так адрес делегата, или циферки?
Если первое - то какой в этом вообще смысл? Его адрес - фактически адрес ссылки на класс делегата где-то в куче. Что вы с этим собираетесь делать? CLR сама выполнит маршаллинг этого делегата без всяких манипуляций с адресами, нужно просто передать его в unmanaged-метод как обычный делегат, точно так же, как это делается и для managed-методов.
Если второе - то эти циферки передаются в метод делегата в неуправляемом коде, на то он и коллбэк. Сами вы до них не доберётесь.
Вот простейший пример с винапишным EnumWindows:
Код: 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.
public class Program
{
  static void Main()
  {
    foreach(var s in FindWindows("Visual"))
      Console.WriteLine(s);
  }

  static IEnumerable<string> FindWindows(string captionPart)
  {
    var found = new List<string>();
    // hwnd и lParam в делегат передаёт внутренняя реализация EnumWindows
    EnumWindows((hwnd, lParam) => 
    {
      var caption = GetWindowText(hwnd);
      if (caption.IndexOf(captionPart, StringComparison.Ordinal) != -1)
        found.Add(caption);
      return true;
    }, IntPtr.Zero);
    return found;
  }

  static string GetWindowText(IntPtr hWnd)
  {
    var size = GetWindowTextLength(hWnd);
    if (size <= 0) return string.Empty;
    var builder = new StringBuilder(size + 1);
    GetWindowText(hWnd, builder, builder.Capacity);
    return builder.ToString();
  }

  delegate bool EnumWindowsProc(IntPtr hWnd, IntPtr lParam);
  [DllImport("user32.dll", CharSet = CharSet.Unicode)]
  static extern int GetWindowText(IntPtr hWnd, StringBuilder strText, int maxCount);
  [DllImport("user32.dll", CharSet = CharSet.Unicode)]
  static extern int GetWindowTextLength(IntPtr hWnd);
  [DllImport("user32.dll")]
  static extern bool EnumWindows(EnumWindowsProc enumProc, IntPtr lParam);
}


Код: plaintext
1.
2.
Microsoft Visual Studio
test (Running) - Microsoft Visual Studio
Visual Studio Application Management Window
...
Рейтинг: 0 / 0
Как получить фактический адрес делегата?
    #40067513
fkthat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Сон Веры Павловны
Так адрес делегата, или циферки?
Если первое - то какой в этом вообще смысл?

Особенно учитывая, что мусорщик в любой момент может все это передвинуть в другое место.
...
Рейтинг: 0 / 0
Как получить фактический адрес делегата?
    #40067585
Фотография Где-то в степи
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
имхо компилятор и может и заинлайнить если нет замыкания, тогда и искать нечего..
...
Рейтинг: 0 / 0
Как получить фактический адрес делегата?
    #40067597
iskatelsql
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Я понимаю, что при передаче делегата в качестве параметра с ним происходят некоторые преобразования, закрепление в памяти или что-то в этом роде. Удивительно что этого нельзя сделать вручную, столько инструментов в шарп понапихано...

Вообще я хочу впилить callback туда, где его изначально не задумано.
Т.е. я из нативной dll вызываю функцию f(), а она в своих недрах вызывает внутреннюю функцию x().
И я думал прямой записью в память поменять call x на call 'адрес делегата'

Ну можно конечно на сях написать обертку для той dll, объявив для f() еще один параметр - адрес callback и переписывать память из обертки... А из шарпа правда чтоль никак? Он ведь даже смешанные dll умеет...
...
Рейтинг: 0 / 0
Как получить фактический адрес делегата?
    #40067601
Сон Веры Павловны
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ну можно конечно попробовать Marshal.GetFunctionPointerForDelegate . Только как бы с таким цирком не получилось выстрелить себе в ногу.
...
Рейтинг: 0 / 0
Как получить фактический адрес делегата?
    #40067603
iskatelsql
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Сон Веры Павловны,

Вот это похоже то что нужно. Но смущает одна там ремарка:

"Вы должны вручную предотвратить сбор делегата сборщиком мусора из управляемого кода. Сборщик мусора не отслеживает ссылки на неуправляемый код. "

Появился второй вопрос... Как это изобразить?
...
Рейтинг: 0 / 0
Как получить фактический адрес делегата?
    #40067613
Фотография Где-то в степи
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
iskatelsql,
наверное можно пробовать в не безопасном режиме, ( указатели цементируются в контексте GC), но имхо прокси лучше.
компромисный вариант - как костыль..( не типичный код )
...
Рейтинг: 0 / 0
Как получить фактический адрес делегата?
    #40067615
fkthat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
iskatelsql
Сон Веры Павловны,

Вот это похоже то что нужно. Но смущает одна там ремарка:

"Вы должны вручную предотвратить сбор делегата сборщиком мусора из управляемого кода. Сборщик мусора не отслеживает ссылки на неуправляемый код. "

Появился второй вопрос... Как это изобразить?


https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/fixed-statement
...
Рейтинг: 0 / 0
Как получить фактический адрес делегата?
    #40067622
Сон Веры Павловны
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
iskatelsql
Как это изобразить?

Просто следить, чтобы код, в котором живёт экземпляр делегата, не мог быть подобран мусурщиком - закреплять ссылку на делегат в виде поля класса, инкапсулирующий ссылку класс закреплять в виде поля в другом классе, итд итп. Например, вот здесь
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
class Foo
{
  public void Bar()
  {
    SomeAction func = n => Console.WriteLine("Passed: {0}", n);
    var ptr = Marshal.GetFunctionPointerForDelegate(func);
    Task.Run(() => Zot(ptr));
  }

  void Zot(IntPtr ptr)
  {
    /*some long operation */
    CallFromNative(ptr);
  }

  delegate void SomeAction(int n);
  [DllImport("mylib.dll")]
  static extern void CallFromNative(IntPtr ptr);
}


в релизной конфигурации к моменту вызова CallFromNative мусорщик уже может убить делегат после выхода из метода Bar, т.к. никакой managed-код эту ссылку не использует. И переданный ptr будет ссылаться на несуществующий метод. И будут сюрпризы - access violation, молчаливый вылет, итд. Это именно то, что я имел в виду выше под выстрелом в ногу.
...
Рейтинг: 0 / 0
Как получить фактический адрес делегата?
    #40067625
Фотография ЕвгенийВ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
fkthat
iskatelsql
Сон Веры Павловны,

Вот это похоже то что нужно. Но смущает одна там ремарка:

"Вы должны вручную предотвратить сбор делегата сборщиком мусора из управляемого кода. Сборщик мусора не отслеживает ссылки на неуправляемый код. "

Появился второй вопрос... Как это изобразить?


https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/fixed-statement

https://docs.microsoft.com/ru-ru/dotnet/api/system.runtime.interopservices.gchandle?view=net-5.0
...
Рейтинг: 0 / 0
Как получить фактический адрес делегата?
    #40070461
Сон Веры Павловны
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Оказывается (это к вопросу про выстрел в ногу) у Marshal.GetFunctionPointerForDelegate и последующего вызова Marshal.GetDelegateForFunctionPointer есть интересные сайд-эффекты (да, это запрещено в документации, а на практике - ради б-га, на свой страх и риск).
...
Рейтинг: 0 / 0
12 сообщений из 12, страница 1 из 1
Форумы / WinForms, .Net Framework [игнор отключен] [закрыт для гостей] / Как получить фактический адрес делегата?
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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