C ++ Как заменить функцию, но при этом использовать в ней оригинальную функцию? - PullRequest
3 голосов
/ 16 августа 2010

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

Так как мне это сделать?

Редактировать: Теперь, когда я подумал об этом, проверка, следует ли мне связывать текстуру или нет, совершенно бесполезна, поскольку, вероятно, opengl уже делает это.Но мне все еще нужно следить за ранее использованной текстурой.

Ответы [ 6 ]

7 голосов
/ 16 августа 2010

Как говорит Андреас в комментарии, вы должны убедиться, что это необходимо.Тем не менее, если вы хотите сделать это, и вы используете компоновщик gnu (вы не указываете операционную систему), вы можете использовать опцию компоновщика:

--wrap glBindTexture

(если передано непосредственно в gcc, вам следуетзапись):

-Wl,--wrap,glBindTexture

Поскольку это делается на этапе компоновщика, вы можете использовать новую функцию с уже существующей библиотекой (редактировать: под «библиотекой» я имею в виду некоторый существующий код, который вы можете перекомпилировать, но которыйне хотел бы изменить).

Код для функции замены будет выглядеть так:

void * __wrap_glBindTexture (GLenum target, GLuint texture) {
   printf ("glBindTexture wrapper\n");
   return __real_glBindTexture (target,texture);
}
3 голосов
/ 16 августа 2010

Вы на самом деле можете сделать это. Посмотрите на LD_PRELOAD. Создайте общую библиотеку, которая определяет glBindTexture. Чтобы вызвать оригинальную реализацию из оболочки, dlopen настоящая библиотека OpenGL и используйте dlsym для вызова нужной функции оттуда.

Теперь имейте весь клиентский код LD_PRELOAD вашей разделяемой библиотеки, чтобы их вызовы OpenGL передавались вашей обертке.

Это наиболее распространенный метод перехвата и изменения вызовов общих библиотек.

1 голос
/ 16 августа 2010

Вы можете перехватить и заменить все вызовы на glBindTexture.Для этого вам нужно создать свою собственную DLL OpenGL, которая перехватывает все вызовы функций OpenGL, выполняет необходимую вам бухгалтерию, а затем перенаправляет вызовы функций в настоящую DLL OpenGL.Это много работы, поэтому я бы определенно подумал дважды, прежде чем идти по этому пути ...

Такие программы, как GLIntercept , работают следующим образом.

0 голосов
/ 17 августа 2010

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

Тем не менее, это еще лучшая идея для разделения проблем: пусть openGL с низким уровнем разбирается со своими вещами низкого уровня, а ваш (тонкий, толстый, как вы хотите) слой абстракции - с более высоким уровнемвещи.

Итак, создайте функцию oglWrapper :: BindTexture, которая выполняет if (), но вы не должны играть с LD, даже если это технически возможно.

[EDIT] На самом деле,это не в спецификации ogl, но все же.

0 голосов
/ 16 августа 2010

Одна возможность - использовать макрос для замены существующих вызовов glBindTexture:

#define glBindTexture(target, texture) myGlBindTexture(target, texture)

Затем в своем коде, где вы хотите защитить себя от использования макроса, вы заключаете имя в скобки:

(glBindTexture)(someTarget, someTexture);

Функциональный макрос можно заменить только тогда, когда за именем сразу следует открывающая скобка, поэтому это предотвращает расширение макроса.

Поскольку это макрос, он влияет только на исходный код, скомпилированный с видимым макросом, но не на существующую DLL, статическую библиотеку и т. Д.

0 голосов
/ 16 августа 2010

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

...