Реализация сырого сундука в стиле v-table thunks - последнее средство. Скорее всего, все, что вам нужно для достижения, может быть достигнуто с помощью функции обертки, и это будет гораздо менее болезненным.
В общем, преобразователь выполняет следующие функции:
- Исправить входные параметры (например, преобразовывать в другой формат)
- вызовов реальное осуществление
- Очистка шаг 1/исправить выходные параметры
чтобы увидеть пример того, как это работает, давайте обратимся к нашему хорошему другу Raymond Chen и его обсуждение регулировочных санков:
http://blogs.msdn.com/oldnewthing/archive/2004/02/06/68695.aspx
преобразователь он использовал следующим образом:
[thunk]:CSample::QueryInterface`adjustor{4}':
sub DWORD PTR [esp+4], 4 ; this -= sizeof(lpVtbl)
jmp CSample::QueryInterface
Как он описывает, у вас есть класс, который реализует те же методы через несколько интерфейсов, поэтому он имеет несколько V-таблиц. (Если вы не знаете COM, все, что вам нужно знать, это то, что он напрямую работает с v-таблицами, поэтому указатель на определенный интерфейс должен содержать указатели на все методы этого интерфейса в порядке.)
Если вы реализуете два интерфейса с различными методами в определенном слоте, вам нужно несколько v-таблиц. Но вы только пишете перекрывающиеся методы один раз, так что метод должен иметь возможность работать с обоими «этими» указателями.Для этого компилятор генерирует метод, необходимый для исправления, и вызывает исходную реализацию.
Таким образом, это делает преобразователь следующие шаги:
- Исправить входные параметры, а именно скрытый «это» указатель, в первой строке.
- Вызовите реальную реализацию во второй строке.
- Cleanup: нет необходимости (см ниже)
Это где jmp
инструкция поставляется в норме, если вы должны были вызвать функцию с помощью call
, он вернется к вам, и вы должны были бы. ret
обратно к вашему абоненту. Поскольку нет никакой очистки, компилятор делает оптимизацию, где он перемещает выполнение прямо к реальной реализации, и давайте возвращаем оператор реальной реализации к вашим вызывающим абонентам. Это только оптимизация, а не фундаментальная часть thunking. Например, 16/32-битные thunks преобразуют входные/выходные параметры между 16 и 32 битами по мере необходимости, поэтому он не может пропустить этап очистки; он должен быть call
, а не jmp
.
Мораль этой истории: если вам нужно что-то сделать, например, оптимизацию jmp
, которую вы не можете написать непосредственно на C++ или на другом языке высокого уровня по выбору, продолжайте и напишите язык ассемблера , В противном случае просто напишите обертку и сделайте это.
Честно говоря, похоже, что вы просите оптимизацию производительности, и большую часть времени (1) компилятор лучше оптимизирует, чем мы думаем, и (2) он не даст вам такого большого улучшения как ты думаешь.
Не могли бы вы прояснить свой вопрос? На данный момент, вместе с вашими комментариями, это выглядит так: «Расскажите мне обо всем, что связано с thunks», что немного ... широкое. – peterchen