Есть много возможностей. Вот один. Вы можете использовать структуру, которая определяет ваш интерфейс
typedef struct {
void* method1(void);
void* method2(void);
void* method3(void);
} interface;
В зависимости от параметров, которые вы передаете из командной строки в main (), вы инициализируете этот интерфейс различными методами
interface *i;
switch (option) {
case VERBOSE: i->method1=verbose_m1; i->method2=verbose_m2; ...a.s.o.
break;
case DEBUG: i->method1=debug_m1; i->method2=debug_m2; ...a.s.o.
break;
default: i->method1=m1; i->method2=m2; i->method3=m3;
}
и вы пишете один код, в который звоните i->method1
.
Для этого есть более элегантные методы: использование классов uml или type и т. Д. Эти элегантные методы будут генерировать низкоуровневый код, а на вашей стороне вы определяете интерфейс на простом языке и т. Д. Чтобы увидеть, как выглядит такой язык например, вы можете просмотреть asdl , который в этом духе очень прост.