Создайте файл .so, смешав C и C для DPI-C

#c #c #gcc #system-verilog

Вопрос:

У меня есть несколько файлов .c и .cpp, которые я хочу подключить к системному тестовому стенду Verilog в виде одного общего объектного файла .so. Подход, который я использовал, состоял в использовании отдельных файлов .o, скомпилированных в один файл .so, который затем был добавлен во время компиляции vcs с остальными файлами SV.

   gcc -w -pipe -fPIC -O -c        file1.c   -o file1.o
  gcc -w -pipe -fPIC -O -c -x c   file2.cpp -o file2.o
  gcc -shared -o libr.so file1.o file2.o
 

При таком подходе компиляция C-кода проходит без ошибок, но когда я пытаюсь скомпилировать верстак verilog вместе с libr.so файл, я получаю ошибки компиляции «неопределенная ссылка». Таким образом, похоже, что связь между файлами c и c нарушена, и компиляция vcs завершается неудачно. Файл c написан в стиле c, поэтому, когда я изменяю расширение file2.cpp в файле 2.c все компилируется и работает так, как ожидалось.

Интерфейс между SV и DPI осуществляется через файл .c. То есть SV вызывает функцию из файла .c, которая затем вызывает другую функцию из файла .cpp. Ошибка заключается в «неопределенной ссылке» на функцию в файле .cpp.

Я нашел несколько примеров, показывающих, как скомпилировать файлы c ИЛИ c в системный верстак verilog, но не смог найти примеров, сочетающих c и c . Таким образом, проблема, по-видимому, связана со смешиванием файлов c и c .

Поддерживается ли вообще смешивание в компиляторе Synopsys VCS? Верны ли мои команды компиляции сверху? Есть какие-нибудь идеи о том, что может быть не так?

Ответ №1:

Чтобы вызвать функцию c из «c», функция c должна быть объявлена с extern "C" привязкой, например:

 extern "C" void foo(int);
 

или

 extern "C" {
   void bar();
}
 

Теперь вы можете позвонить foo(3) или bar() с «с»

Кроме того, вам не нужен дополнительный файл » c » для определения функций DPI в системном журнале версий. Вы все еще можете использовать extern "C" в своих файлах c и использовать эти функции для точек на дюйм.

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

1. В крайнем случае extern "C"{ #include"cheader.h" } , я думаю, можно было бы обойтись.

2. @Serge итак, вы хотите сказать, что содержимое каждого файла .cpp, который я использую, должно быть заключено в extern "C"{} ?

3. Нет, я ничего не говорил обо всем контексте c . Только определения функций в файлах c , доступ к которым осуществляется с помощью DPI или из программы «c», должны быть заключены во внешнее «C» {…} . Все обычные имена функций c искажены в объектных файлах. Имена функций C не искажены. внешний C предотвращает их искажение c .

4. @Serge вы правы — не имело бы смысла заключать в это все файлы. Однако, когда я вызываю foo1(), который вызывает foo2(), который вызывает foo3(), откуда они берутся .c, .cpp, .cpp файлы соответственно, компилятор жалуется на то, что foo3() не определен. Итак, заключение, по-видимому, необходимо. Должно быть, я чего-то не понимаю…

5. вам нужно привести пример. «foo1″ находится в файле » c «и скомпилирован компилятором «c», он может вызывать «foo2», только если foo2 объявлен как внешний «C» в файле cpp. ‘foo2’, в свою очередь, может вызывать любую функцию c с или без внешнего «C». Если вы хотите вызвать функцию » c » из » c «, вам также необходимо объявить ее проптотип как внешний «C». Если в этой схеме отсутствуют символы, это означает только то, что вы не предоставляете все файлы, необходимые для связывания.