c ++ / c # Маршалл структуры, чтобы получить фиксированный указатель - PullRequest
1 голос
/ 04 мая 2011

У меня есть старое приложение, которое принимает плагины dll.Каждый плагин имеет функцию, которая создает новый экземпляр «виджета».Эта функция идентифицирует новый экземпляр "виджета", возвращая уникальный int .В шаблоне плагина c ++ я сделал это, объявив новый виджет struct и вернув его указатель в виде уникального идентификатора int (не моя идея, но я должен работать сэто):

struct widget {
    ...
};

int widget_instance (HWND hwnd) {
    widget* myWidget = new widget;
    ...
    return (int) myWidget;
}

Я работаю над плагином ac # для этого приложения, и мне нужно скопировать этот механизм в c #.Как объявить структуру внутри функции, чтобы при каждом вызове функции она возвращала фиксированный неизменяемый указатель на вновь объявленную структуру?Мой код пока:

public struct Widget {
   ...
}

public static int widget_instance(uint hwnd) {
    Widget w = new Widget();
    ...
    IntPtr myWidget = Marshal.AllocCoTaskMem(Marshal.SizeOf(w));
    Marshal.StructureToPtr(w, myWidget, false);
    return (int) myWidget;
}

Кажется ли это правильным?Нужно ли мне «закрепить» структуру, чтобы это работало так, как это делает с ++?

РЕДАКТИРОВАТЬ: Чтобы уточнить: уникальный идентификатор - это не просто «cookie» int , это фактическипозже используется в шаблоне c ++ для доступа к экземпляру struct путем приведения идентификатора в качестве указателя:

widget* w = (widget*) WidgetID;
w->firstElement = 123;

Я предполагаю, что эквивалент c # будет:

widget w = (widget)Marshal.PtrToStructure((IntPtr)widgetID,typeof(widget));
w.firstElement = 123;

Ответы [ 2 ]

1 голос
/ 04 мая 2011

Похоже, вы подразумеваете, что возвращенный целочисленный идентификатор является просто файлом cookie и не рассматривается приложением как указатель.Это будет означать, что приложение никогда не выполняет операции с виджетом, но всегда просит плагин выполнить операции от имени приложения.Если это так, то нет причин, по которым вы не можете использовать свою собственную схему для назначения идентификаторов cookie.Итак ...

Вы можете добавить член "cookie" в свой класс Widget и статический член "следующий cookie" для назначения файлов cookie.Это будет простая и семантически обоснованная реализация.Очевидно, что это потребует мер безопасности потока.Это также позволило бы избежать техники приведения C ++ для приведения указателя this к int, что, как вы говорите, вам не нравится, хотя я думаю, что это совершенно нормально.вторая цель в дополнение к предоставлению уникального идентификатора.Когда приложение дает плагину cookie, плагин может найти виджет напрямую и при нулевых затратах времени выполнения, возвращая cookie обратно к указателю.Хотя это вряд ли безопасно.Но я не думаю, что вы все равно можете сделать это в C #.

Предложенный вами код C # означает, что для каждого виджета, который запрашивает приложение, вы хотите только создать и инициализировать второй виджет.Если вы действительно хотите имитировать технику C ++, чтобы ваши куки гарантированно были уникальными для всего процесса, а не просто уникальными для одного плагина, вы можете просто выделить однобайтовый блок, но не инициализировать его.Или даже блок нулевого размера, но я не совсем уверен, что это даст уникальные адреса.

0 голосов
/ 04 мая 2011

Да, это правильно, поскольку AllocCoTaskMem выделяет память из неуправляемого COM-распределителя.

Память освобождается или перемещается только с функциями FreeCoTaskMem или ReAllocCoTaskMem соответственно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...