Неопределенная ошибка ссылки в ссылке с использованием ключевого слова extern - PullRequest
0 голосов
/ 25 января 2019

У меня проблема со связью между двумя библиотеками libA.a (статическая) и libB.so (динамическая), созданная из исходников C.

В одном из исходных файлов, использованных для генерации libB.so,У меня есть следующие функции:

static uint64_t unassigned_mem_read(void *opaque, hwaddr addr, unsigned size) { ... }
static void unassigned_mem_write(void *opaque, hwaddr addr, uint64_t val, unsigned size) { ... }

Когда я запускаю nm libB.so | grep unassigned_mem, у меня есть:

00000000004662a7 t unassigned_mem_read
0000000000466337 t unassigned_mem_write

И в исходном файле, используемом для создания libA.a, я имеюgot:

extern uint64_t unassigned_mem_read(void *opaque, hwaddr addr, unsigned size);
extern void unassigned_mem_write(void *opaque, hwaddr addr, uint64_t val, unsigned size);

и чуть дальше эти методы вызываются.

Когда я компилирую, все в порядке.Но тогда по ссылке у меня есть:

[build] qmg-mmio.c:47: undefined reference to 'unassigned_mem_read'
[build] qmg-mmio.c:84: undefined reference to 'unassigned_mem_write'

Когда я делаю nm libA.a | grep unassigned_mem У меня есть:

U unassigned_mem_read
U unassigned_mem_write

Я связываю в следующем порядке: libB.so, libA.a.

Поскольку символы одинаковы, что может сделать их неразрешимыми?

Более того, когда я собираю все исходники вместе, у меня не возникает проблем с ссылками.Есть ли какая-то хитрость при объединении статической и динамической библиотек, которые мне не хватает?

1 Ответ

0 голосов
/ 25 января 2019

Для идентификаторов области файла ключевое слово static указывает внутреннюю связь . Это означает, что идентификатор и любое связанное с ним определение по существу являются частными для единицы перевода, в которой они появляются. Чтобы не было путаницы, обратите внимание, что это только периферийно связано со «статическими библиотеками», и особенно то, что функции в статических библиотеках, которые предназначены для непосредственного вызова пользователями библиотеки, должны не быть объявленными static , так как это прямо и конкретно предотвращает подобные звонки.

Связывание - это свойство идентификаторов в своих областях, а не объектов или функций, которые они идентифицируют, и необязательно того же идентификатора в других областях. Более того, один и тот же идентификатор может быть связан с разными объектами и / или функциями в разных областях. В частности, объявление extern al данного идентификатора связано с функцией или объектом, отличным от тех, которые связаны с любыми внутренними объявлениями того же идентификатора, поэтому вы не можете переопределить внутреннее объявление, появляющееся в одной области видимости, как внешнее, добавив объявление в какой-то другой области.

Поскольку вы, похоже, неохотно модифицируете библиотеку, содержащую функции, которые вы хотите вызвать, я полагаю, что она предоставлена ​​третьей стороной. В этом случае вы должны понимать, что часть объявления этих функций static заключается в том, что вы , пользователь библиотеки не вызывают их напрямую. Они не являются частью внешнего интерфейса библиотеки.

...