visual studio c компоновщиком?
Из этой статьи Модульное тестирование с фиктивными объектами в C
Это делается с помощью опции компоновщика --wrap, которая принимает имя обернутой функции в качестве аргумента. Если тест был скомпилирован с использованием gcc, вызов может выглядеть следующим образом:
$ gcc -g -Wl,--wrap=chef_cook waiter_test.c chef.c
Как я могу сделать это при компиляции AC проекта в Visual Studio?
1 ответ
В
--wrap
в
ld
может быть эмулирован
/ALTERNATENAME
вариант в компоновщике MSVC.
Мы начинаем с двух единиц компиляции, скажем, скомпилированных из
foo.c
, чьи внешние функции объявлены в, и
main.o
из . (Если он был скомпилирован как библиотека, многое не изменится.)
// foo.h
int foo();
// foo.c
int foo() {
return 0;
}
// main.c
#include <stdio.h>
#include "foo.h"
int main() {
int x = foo();
printf("%s\n", x ? "wrapped" : "original");
}
Возвращаемое значение равно 0, поэтому приведенный выше фрагмент кода выведет «оригинал».
Теперь мы заменяем фактическую реализацию псевдонимом:
#include "foo.h"
в
main.c
заменяется на
#define foo real_foo
#include "foo.h"
#undef foo
#pragma comment(linker, "/alternatename:real_foo=foo")
Позвольте мне объяснить, что здесь происходит:
- к
#define foo real_foo
, объявление функции вfoo.h
модифицируется как. - Однако символ в
foo.o
по-прежнему назван в честь, а не псевдонимом. Вот почему нам нужен/alternatename
переключатель компоновщика. -
"/alternatename:real_foo=foo"
сообщает компоновщику, что если вы не можете найти символ с именемreal_foo
, пытатьсяfoo
еще раз, прежде чем выбросить ошибку. - Видимо нет определения. Компоновщик MSVC будет искать и связывать его вместо этого при каждом появлении
int real_foo()
.
Поскольку предыдущая реализация была псевдонимом, теперь мы перенаправляем
int foo()
в нашу новую реализацию макросом:
int wrap_foo() {
return real_foo() + 1;
}
#define foo wrap_foo
И мы здесь закончили. Наконец то
main.cpp
похоже:
#include <stdio.h>
#define foo real_foo
#include "foo.h"
#undef foo
#pragma comment(linker, "/alternatename:real_foo=foo")
int wrap_foo() {
return real_foo() + 1;
}
#define foo wrap_foo
int main() {
int x = foo();
printf("%s\n", x ? "wrapped" : "original");
}
Построенный в MSVC, он будет выводить «завернутый».