Ошибки компоновщика могут произойти, если заголовочный файл и связанная с ним общая библиотека (файл .lib) не синхронизируются. Позволь мне объяснить.
Как работают линкеры? Линкер соответствует объявлению функции (объявленному в заголовке) с его определением (в общей библиотеке) путем сравнения их подписи. Вы можете получить ошибку компоновщика, если компоновщик не найдет определение функции, которое идеально подходит.
Возможно ли получить ошибку компоновщика, даже если объявление и определение, похоже, совпадают? Да! Они могут выглядеть одинаково в исходном коде, но это действительно зависит от того, что видит компилятор. По сути, вы можете столкнуться с такой ситуацией:
// header1.h
typedef int Number;
void foo(Number);
// header2.h
typedef float Number;
void foo(Number); // this only looks the same lexically
Обратите внимание, что хотя обе декларации функций выглядят одинаково в исходном коде, но они действительно различаются в зависимости от компилятора.
Вы можете спросить, как это получается в такой ситуации? Включите пути, конечно! Если при компиляции разделяемой библиотеки путь include приводит к header1.h
, и вы в конечном итоге используете header2.h
в своей собственной программе, вы оставите царапины на своем заголовке, задаваясь вопросом, что произошло (каламбур).
Пример того, как это может произойти в реальном мире, объясняется ниже.
У меня есть два проекта: graphics.lib
и main.exe
. Оба проекта зависят от common_math.h
. Предположим, что библиотека экспортирует следующую функцию:
// graphics.lib
#include "common_math.h"
void draw(vec3 p) { ... } // vec3 comes from common_math.h
И затем вы идете вперед и включаете библиотеку в свой собственный проект.
// main.exe
#include "other/common_math.h"
#include "graphics.h"
int main() {
draw(...);
}
Boom! Вы получаете ошибку компоновщика, и вы понятия не имеете, почему она терпит неудачу. Причина в том, что общая библиотека использует разные версии одного и того же include common_math.h
(я сделал это очевидным здесь в этом примере, включив другой путь, но это может быть не всегда так очевидно. Возможно, путь include отличается в настройки компилятора).
Обратите внимание, что в этом примере компоновщик сказал бы вам, что не смог найти draw()
, когда на самом деле вы знаете, что он явно экспортируется библиотекой. Вы могли часами царапать себе голову, думая, что пошло не так. Дело в том, что компоновщик видит другую подпись, потому что типы параметров немного отличаются. В этом примере vec3
является другим типом в обоих проектах в отношении компилятора. Это может произойти из-за того, что они происходят из двух немного разных файлов include (возможно, включенные файлы поступают из двух разных версий библиотеки).
DUMPBIN - ваш друг, если вы используете Visual Studio. Я уверен, что другие компиляторы имеют другие подобные инструменты.
Процесс выглядит следующим образом:
[1] По проекту я имею в виду набор исходных файлов, которые связаны друг с другом для создания либо библиотеки, либо исполняемого файла .
РЕДАКТИРОВАТЬ 1: Переписать первый раздел, который будет легче понять. Пожалуйста, прокомментируйте ниже, чтобы сообщить мне, нужно ли что-то еще исправлять. Спасибо!
Обратите внимание на .convertBodyTo()
- в частности аргумент charset
.
from("direct:foo").
to("http://foo.com/bar.html").
convertBodyTo(String.class, "UTF-8")
to("file:///tmp/bar.html")
Я думаю, что решение vikingsteve пропускает шаг. Входной поток содержит символы с кодировкой CP1251. Символы в этом потоке не изменят свою кодировку при преобразовании содержимого входного потока в строку. Вам нужно указать ту же схему кодировки символов, которая использовалась сущностью, которая кодировала символы при их декодировании. В противном случае вы получите нежелательные результаты.
<route id="process_umlaug_file" startupOrder="2">
<from uri="file:///home/steppra1/Downloads?fileName=input_umlauts.txt"/>
<convertBodyTo type="java.lang.String" charset="ISO-8859-1"/>
<to uri="file:///home/steppra1/Downloads?fileName=output_umlauts.txt&charset=UTF-8"/>
</route>
Я проверил это чтение файла с кодировкой CP1251, содержащего немецкие умлауты:
steppra1@steppra1-linux-mint ~/Downloads $ file input_umlauts.txt
input_umlauts.txt: ISO-8859 text, with CRLF line terminators
steppra1@steppra1-linux-mint ~/Downloads $ file output_umlauts.txt
output_umlauts.txt: UTF-8 Unicode text, with CRLF line terminators
Используя два этапа декодирования, а затем повторное кодирование дает надлежащим образом закодированные немецкие умлауты. Если я перехожу выше маршрута в
<route id="process_umlaug_file" startupOrder="2">
<from uri="file:///home/steppra1/Downloads?fileName=input_umlauts.txt"/>
<convertBodyTo type="java.lang.String" charset="UTF-8"/>
<to uri="file:///home/steppra1/Downloads?fileName=output_umlauts.txt"/>
</route>
, тогда выходной файл по-прежнему кодируется UTF-8, возможно, потому что это моя платформа по умолчанию, но умляуты искажены.