Есть ли способ переопределить основную функцию модуля на языке программирования D?

#attributes #d #main #weak #scriptedmain

#атрибуты #d #program-entry-point #слабый #scriptedmain

Вопрос:

Если вам действительно нужно, вы можете указать __attribute__((weak)) на C (см. scriptedmain ). Это позволяет программе работать как с API, так и с исполняемым файлом, позволяя коду, который импортирует API, перезаписывать основную функцию.

Есть ли у D способ сделать это? У Python есть if __name__=="__main__": main() , но weak синтаксис в C кажется намного ближе.

Ответ №1:

Да, с использованием директив версии, которые требуют специальных опций для rdmd и dmd.

scriptedmain.d:

 #!/usr/bin/env rdmd -version=scriptedmain

module scriptedmain;

import std.stdio;

int meaningOfLife() {
    return 42;
}

version (scriptedmain) {
    void main(string[] args) {
        writeln("Main: The meaning of life is ", meaningOfLife());
    }
}
  

test.d:

 #!/usr/bin/env rdmd -version=test

import scriptedmain;
import std.stdio;

version (test) {
    void main(string[] args) {
        writeln("Test: The meaning of life is ", meaningOfLife());
    }
}
  

Пример:

 $ ./scriptedmain.d
Main: The meaning of life is 42
$ ./test.d
Test: The meaning of life is 42
$ dmd scriptedmain.d -version=scriptedmain
$ ./scriptedmain
Main: The meaning of life is 42
$ dmd test.d scriptedmain.d -version=test
$ ./test
Test: The meaning of life is 42
  

Также опубликовано на RosettaCode.

Комментарии:

1. Технически вы не переопределяете main, а используете условную компиляцию. Это ближе к #ifdef , чем к __attribute__ .

2. вы можете использовать pragma(startaddress,foo) операторы wrapped in version для получения того же результата без переноса основных функций в версии

3. @ratchetfreak Круто! Пожалуйста, приведите полный пример его использования.

Ответ №2:

Я считаю __attribute__((weak)) , что это расширение GNU, которое выдает специальные инструкции компоновщика для слабой компоновки, поэтому оно очень специфично для набора инструментов. В DMD нет ничего для этого AFAIK, но другие общие компиляторы (GDC или LDC) могут поддерживать расширения своих бэкэндов.

Ответ №3:

IIRC существует способ заставить код компилироваться в библиотеку, а не в объектный файл. Из-за того, как компоновщик выполняет поиск объектов, вы можете использовать это для получения того же эффекта; просто поместите цель с main, которую вы хотите использовать первой в порядке ссылки.