Что такое «неопределенный ссылочный / неразрешенный внешний символ»
Я попытаюсь объяснить, что такое «неопределенный ссылочный / неразрешенный внешний символ».
note : я использую g ++ и Linux, и все примеры для него
blockquote>Например, у нас есть некоторый код
// src1.cpp void print(); static int local_var_name; // 'static' makes variable not visible for other modules int global_var_name = 123; int main() { print(); return 0; }
и
// src2.cpp extern "C" int printf (const char*, ...); extern int global_var_name; //extern int local_var_name; void print () { // printf("%d%d\n", global_var_name, local_var_name); printf("%d\n", global_var_name); }
Создание объектных файлов
$ g++ -c src1.cpp -o src1.o $ g++ -c src2.cpp -o src2.o
После фазы ассемблера у нас есть объектный файл, который содержит любые экспортируемые символы. Посмотрите на символы
$ readelf --symbols src1.o Num: Value Size Type Bind Vis Ndx Name 5: 0000000000000000 4 OBJECT LOCAL DEFAULT 4 _ZL14local_var_name # [1] 9: 0000000000000000 4 OBJECT GLOBAL DEFAULT 3 global_var_name # [2]
Я отклонил некоторые строки из вывода, потому что они не имеют значения
Итак, мы видим следующие символы для экспорта.
[1] - this is our static (local) variable (important - Bind has a type "LOCAL") [2] - this is our global variable
src2.cpp ничего не экспортирует, и мы не видели его символов
Свяжите наши объектные файлы
$ g++ src1.o src2.o -o prog
и запустите его
$ ./prog 123
Linker видит экспортированные символы и связывает их. Теперь мы пытаемся раскомментировать строки в src2.cpp, как здесь
// src2.cpp extern "C" int printf (const char*, ...); extern int global_var_name; extern int local_var_name; void print () { printf("%d%d\n", global_var_name, local_var_name); }
, и перестроить объектный файл
$ g++ -c src2.cpp -o src2.o
OK (нет ошибок), потому что мы только строим объектный файл, связь еще не завершена. Попробуйте установить ссылку
$ g++ src1.o src2.o -o prog src2.o: In function `print()': src2.cpp:(.text+0x6): undefined reference to `local_var_name' collect2: error: ld returned 1 exit status
Это произошло потому, что наше local_var_name статично, то есть оно не отображается для других модулей. Теперь глубже. Получить выход фазы перевода
$ g++ -S src1.cpp -o src1.s // src1.s look src1.s .file "src1.cpp" .local _ZL14local_var_name .comm _ZL14local_var_name,4,4 .globl global_var_name .data .align 4 .type global_var_name, @object .size global_var_name, 4 global_var_name: .long 123 .text .globl main .type main, @function main: ; assembler code, not interesting for us .LFE0: .size main, .-main .ident "GCC: (Ubuntu 4.8.2-19ubuntu1) 4.8.2" .section .note.GNU-stack,"",@progbits
Итак, мы видели, что для local_var_name нет метки, поэтому линкер не нашел его. Но мы хакеры :), и мы можем это исправить. Откройте src1.s в текстовом редакторе и измените
.local _ZL14local_var_name .comm _ZL14local_var_name,4,4
на
.globl local_var_name .data .align 4 .type local_var_name, @object .size local_var_name, 4 local_var_name: .long 456789
i.e. вам должно быть как ниже
.file "src1.cpp" .globl local_var_name .data .align 4 .type local_var_name, @object .size local_var_name, 4 local_var_name: .long 456789 .globl global_var_name .align 4 .type global_var_name, @object .size global_var_name, 4 global_var_name: .long 123 .text .globl main .type main, @function main: ; ...
мы изменили видимость local_var_name и установили его значение в 456789. Попробуйте построить из него объектный файл
$ g++ -c src1.s -o src2.o
ok, см.
$ readelf --symbols src1.o 8: 0000000000000000 4 OBJECT GLOBAL DEFAULT 3 local_var_name
В настоящее время local_var_name имеет привязку GLOBAL (LOCAL)
link
$ g++ src1.o src2.o -o prog
и запускает ее
$ ./prog 123456789
ok, мы взломаем его:)
Итак, в результате - «неопределенная ссылка / неразрешенная внешняя ошибка символа» происходит, когда компоновщик не может найти глобальные символы в объектных файлах.
Ваш файл main.css повлияет только на содержимое SVG, если SVG-файл включен в HTML:
https://developer.mozilla.org/ ru / docs / SVG_In_HTML_Introduction
<html>
<body>
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 56.69 56.69">
<g>
<path d="M28.44......./>
</g>
</svg>
</html>
Если вы хотите сохранить SVG в файлах, CSS необходимо определить внутри SVG-файла.
Вы можете сделать это с помощью тега стиля:
http://www.w3.org/TR/SVG/styling.html#StyleElementExample
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg xmlns="http://www.w3.org/2000/svg" version="1.1"
width="50px" height="50px" viewBox="0 0 50 50">
<defs>
<style type="text/css"><![CDATA[
.socIcon g {
fill:red;
}
]]></style>
</defs>
<g>
<path d="M28.44......./>
</g>
</svg>
Вы можете использовать инструмент на стороне сервера для обновления тега стиля в зависимости от активного стиля. В рубине вы могли добиться этого с Нокогири. SVG - это просто XML. Таким образом, возможно, существует много доступных XML-библиотек, которые, возможно, могут это достичь.
Если вы не можете этого сделать, вам придется просто использовать их, как если бы они были PNG; создавая набор для каждого стиля и сохраняя их встроенные стили.
Вы можете делать то, что хотите, с одним (важным) предупреждением: пути внутри вашего символа не могут быть созданы независимо через внешний CSS - вы можете только установить свойства для всего символа с помощью этого метода. Итак, если у вас есть два пути в вашем символе и хотите, чтобы у них были разные цвета заливки, это не сработает, но если вы хотите, чтобы все ваши пути были одинаковыми, это должно работать.
В вашем html, вы хотите что-то вроде этого:
<style>
.fill-red { fill: red; }
.fill-blue { fill: blue; }
</style>
<a href="//www.example.com/">
<svg class="fill-red">
<use xlink:href="images/icons.svg#example"></use>
</svg>
</a>
И во внешнем SVG-файле вы хотите что-то вроде этого:
<svg xmlns="http://www.w3.org/2000/svg">
<symbol id="example" viewBox="0 0 256 256">
<path d="M120.... />
</symbol>
</svg>
Поменяйте класс на теге svg
(в вашем html) с fill-red
до fill-blue
и ta-da ... у вас есть синий, а не красный.
Вы можете частично преодолеть ограничение возможности таргетинга на пути отдельно с помощью внешний CSS путем смешивания и сопоставления внешнего CSS с некоторым встроенным CSS на определенных путях, поскольку встроенный CSS будет иметь приоритет. Такой подход будет работать, если вы делаете что-то вроде белого значка на цветном фоне, где вы хотите изменить цвет фона через внешний CSS, но сам значок всегда белый (или наоборот). Итак, с тем же HTML, что и раньше, и что-то вроде этого кода svg, вы получите красный фон и белый путь переднего плана:
<svg xmlns="http://www.w3.org/2000/svg">
<symbol id="example" viewBox="0 0 256 256">
<path class="background" d="M120..." />
<path class="icon" style="fill: white;" d="M20..." />
</symbol>
</svg>
«Я действительно собираюсь изменить цвета этих изображений на основе той цветовой схемы, которую пользователь выбрал для моего сайта». - Jordan 10 часов назад
blockquote>Я предлагаю вам использовать PHP для этого. Нет лучшего способа сделать это без знаковых шрифтов, и если вы будете сопротивляться их использованию, вы можете попробовать следующее:
<?php header('Content-Type: image/svg+xml'); echo '<?xml version="1.0" encoding="utf-8"?>'; $color = $_GET['color']; ?> <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> <svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 56.69 56.69"> <g> <path fill="<?php echo $color; ?>" d="M28.44..."/> </g> </svg>
И позже вы можете использовать этот файл как
filename.php?color=#ffffff
, чтобы получить файл svg в желаемом цвете.
Я знаю его старое сообщение, но просто для устранения этой проблемы ... вы просто используете свои классы не в том месте: D
Прежде всего вы можете использовать
svg { fill: red; }
в вашем main.css
, чтобы он был красным. Это имеет эффект. Вы также можете использовать селектора узлов, чтобы получить конкретные патчи.
Во-вторых, вы объявили класс в img
-Tag.
<img class='socIcon'....
Вы действительно должны объявить его внутри своего SVG. если у вас есть разные пути, которые вы могли бы определить больше, конечно.
<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet href="stylesheets/main.css" type="text/css"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 56.69 56.69">
<g>
<path class="myClassForMyPath" d="M28.44......./>
</g>
</svg>
теперь вы можете изменить цвет в своем main.css
, например
.myClassForMyPath {
fill: yellow;
}
Что работает для меня: тег стиля с правилом @import
<defs>
<style type="text/css">
@import url("svg-common.css");
</style>
</defs>
Этот метод будет работать, если svg будет просмотрен в веб-браузере, но как только этот код будет загружен на сервер, а класс для значка svg будет закодирован, как если бы это было фоновое изображение цвет теряется и возвращается к цвету по умолчанию. Похоже, что цвет не может быть изменен из внешней таблицы стилей, даже если оба класса svg для цвета и класс верхнего уровня для отображения и положения svg отображаются в один и тот же каталог.
Это должно быть возможно сделать, сначала вставив внешние изображения svg. Посмотрите здесь, например:
Можно создать стиль SVG путем динамического создания элемента стиля в JavaScript и добавления его в элемент SVG. Hacky, но он работает.
<object id="dynamic-svg" type="image/svg+xml" data="your-svg.svg">
Your browser does not support SVG
</object>
<script>
var svgHolder = document.querySelector('object#dynamic-svg');
svgHolder.onload = function () {
var svgDocument = svgHolder.contentDocument;
var style = svgDocument.createElementNS("http://www.w3.org/2000/svg", "style");
// Now (ab)use the @import directive to load make the browser load our css
style.textContent = '@import url("/css/your-dynamic-css.css");';
var svgElem = svgDocument.querySelector('svg');
svgElem.insertBefore(style, svgElem.firstChild);
};
</script>
Вы можете генерировать JavaScript динамически на PHP, если хотите - тот факт, что это возможно в JavaScript, открывает множество возможностей.
При использовании в теге <image>
SVG должен содержаться в одном файле по соображениям конфиденциальности. Эта ошибка bugzilla содержит более подробную информацию о том, почему это так. К сожалению, вы не можете использовать другой тег, такой как <iframe>
, потому что это не будет работать как ссылка, поэтому вам придется встроить CSS в тег <style>
внутри самого файла.
Еще один способ сделать это - иметь SVG-данные в основном файле html, т. Е.
<a href='http://youtube.com/...' target='_blank'>
<svg id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 56.69 56.69">
<g>
<path d="M28.44......./>
</g>
</svg>
</a>
. Вы можете создать стиль с помощью внешнего файла CSS с использованием тега HTML <link>
.
Один из подходов, который вы можете предпринять, - это просто использовать фильтры CSS, чтобы изменить внешний вид графики SVG в браузере.
Например, если у вас есть SVG-графический файл, который использует цвет заливки красного цвета внутри SVG-код, вы можете включить его фиолетовым с настройкой поворота оттенка на 180 градусов:
#theIdOfTheImgTagWithTheSVGInIt {
filter: hue-rotate(180deg);
-webkit-filter: hue-rotate(180deg);
-moz-filter: hue-rotate(180deg);
-o-filter: hue-rotate(180deg);
-ms-filter: hue-rotate(180deg);
}
Экспериментируйте с другими настройками поворота, чтобы найти нужные цвета.
Чтобы быть ясным, приведенный выше CSS идет в CSS, который применяется к вашему HTML-документу. Вы ставите тег img в HTML-код, не устраивая код SVG.
И обратите внимание, что это не будет работать с графикой, заполненной черным или белым или серым цветом. Вы должны иметь фактический цвет, чтобы вращать оттенок этого цвета.
Очень быстрое решение для динамического стиля с внешней таблицей стилей CSS, если вы используете тэг <object>
для вставки вашего svg.
В этом примере добавится класс к корню <svg>
при нажатии на родительский элемент.
file.svg:
<?xml-stylesheet type="text/css" href="../svg.css"?>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="">
<g>
<path/>
</g>
</svg>
html:
<a class="parent">
<object data="file.svg"></object>
</a>
JQuery:
$(function() {
$(document).on('click', '.parent', function(){
$(this).find('object').contents().find('svg').attr("class","selected");
}
});
на родительском элементе click:
<svg xmlns="http://www.w3.org/2000/svg" viewBox="" class="selected">
, тогда вы можете управлять своим css
svg.css:
path {
fill:none;
stroke:#000;
stroke-miterlimit:1.41;
stroke-width:0.7px;
}
.selected path {
fill:none;
stroke:rgb(64, 136, 209);
stroke-miterlimit:1.41;
stroke-width:0.7px;
}