Упаковка неуправляемого c' в управляемой обертке

положить (р, бесплатно);

Как я могу подвергать такого рода вещи .NET приложений?

У меня есть неуправляемая библиотека СЗ. Я хотел бы раскрыть функциональность для приложений .NET. Есть одна часть функции, с которой я не знаю, как обращаться:

typedef пустота (free_fn) (пустота);none... заполнить буфер...

Ответ на: "Упаковка неуправляемого c' в управляемой обертке"

Количество ответов:7

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

В целом, пользователи .NET вашей библиотеки не будут передавать динамически созданные массивы вашим функциям. Насколько я знаю, все контейнеры в .NET собраны мусором.

Несмотря на это, вам нужно будет сделать управляемую обертку для вашего неуправляемого кода. Есть много учебников и статей по этому вопросу, here is one to start with. .

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

Если вы действительно хотите реализовать эту функцию для функции в .NET, вам нужно будет посмотреть на Marshal class in .NET for taking control of managed memory in unmanaged code. для принятия контроля над управляемой памятью в неуправляемом коде.

Для функции обратного вызова сначала необходимо создать делегатов .NET, которые могут быть назначены в управляемом коде. Затем вам нужно будет сделать неуправляемую бесплатную функцию внутренней для вашей библиотеки, которая называется неуправляемой версией функции пута. Эта неуправляемая бесплатная функция будет отвечать за вызов управляемого делегата, если назначенный ему пользователь.

Будьте очень осторожны, когда вы делаете это. .NET действительно, действительно хочет, чтобы его объекты были закреплены на пути в неуправляемой рутины и unpinned на выходе. Если ваш неуправляемый код удерживает значение указателя, которое было закреплено на пути в то есть очень реальный шанс, что память будет перемещена или мусор собраны или оба.

Это особенно в случае с делегатами marshalled для функции указателей (поверьте мне на это - я обнаружил, что marshaled делегатов в настоящее время мусор, собранный на меня - у меня были люди в Microsoft проверить, что для меня). Конечным решением этой проблемы является копии делегатов в статической таблице в паре с уникальным идентификатором транзакции, а затем создание неуправляемой функции, которая при вызове смотрит делегата в таблице через идентификатор транзакции, а затем выполняет ее. Это уродливо, и если бы у меня был другой выбор, я бы использовал его.

Вот лучший способ сделать это в вашем случае - так как ваш неуправляемый код использует его и забыть его модель, то вы должны сделать ваш API chunkier. Создайте обертку в управляемом C, который распределяет память с помощью неуправляемой рутины, копирует ваши данные в нее, а затем передает их вместе с указателем неуправляемого сделок.

Вы определенно не хотите, чтобы приколоть управляемый буфер, как пытается deallocate его в неуправляемый код кажется кратчайшим путем к безумию. Если вы не можете переписать эту часть в полностью управляемый код, лучше всего либо сделать копию данных в обертке, либо полностью скрыть управление буфером от управляемого мира.

Если у вас есть кишки (и мазохистской выносливости) вы может приколоть буфер в обертке, а затем пройти в marshaled делегат управляемой функции, которая открепит буфер. Тем не менее, я бы не стал предлагать его. После того, как мне пришлось сделать пару управляемых оберток, научил меня ценности разоблачения абсолютной минимальной неуправляемой функциональности, даже если это означает, что вы должны переписать некоторые вещи в управляемом коде. Пересечение этой границы примерно так же просто, как переход из Восточной Германии в Западную Германию раньше, не говоря уже о производительности хитов.

Функция .Net, подвергающаяся воздействию, принимает только данные, но не принимает делегата. Код передает прикрепленные данные и указатель функции функции, которая просто открепит данные. Это оставляет очистку памяти для GC, но гарантирует, что он не будет чистить его до асинкронозной части сделано.

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

Большинство ответов предполагают, что данные должны быть скопированы из управляемого буфера в неуправляемый буфер. Как именно вы это сделаете? Хорошо ли следить за реализацией?

void managed_put (byte data_ __gc[], size_t size_)
{
    //  Pin the data
    byte __pin *tmp_data = &data_[0];

    //  Copy data to the unmanaged buffer.
    void *data = malloc (size_);
    memcpy (data, (byte*) tmp_data, size_);

    //  Forward the call
    put (data, size_, free);
}

Некоторые из предыдущих плакатов были с помощью MC, который является deprecated. C'/CLI является гораздо более элегантным решения.

ЛУЧШИЕ, техника для интеропа, является неявным интерп, а не явным. Я не верю, что кто-то прокомментировал это еще. Тем не менее, это дает вам возможность маршал ваших типов от управляемого 'lt;-gt;родной, где, если вы внести изменения в тип определения или структуры макета, это не приведет к нарушению изменения (что явное interop делает).

Эта статья wikiepedia документирует некоторые различия и является хорошей отправной точкой для дополнительной информации.

P/Invoke (explicit and implicit)

Кроме того, сайт marshal-as.net has some examples and information as to this newer method (again, more ideal as it will not break your code if the a native struct is re-defined). имеет несколько примеров и информации о том, что этот новый метод (опять же, более идеально, как он не будет нарушать ваш код, если родной структуры реимконал).