Как я могу использовать VTD-XML внутри Perl с Inline :: C? - PullRequest
2 голосов
/ 08 июня 2011

Недавно я обнаружил мощь подхода VTD-XML к анализу XML, главным образом, его скорость.Если говорить точнее, я создал версию C 2.10 (также есть реализации на Java, C ++ и C #).

Моя цель проста: я хочу извлечь данные из XML, используя VTD-XML для анализа, ииспользуя Perl для работы с данными.Самый простой способ - сделать дамп данных с созданной мною программой C и отправить их по конвейеру в программу Perl.Может быть, не элегантно, но это работает.

Другой, менее простой способ состоит из Perl-программы, которая вызывает подпрограмму сборщика данных C с использованием Inline :: C.

Поэтому я начал изучать Inline ::C и удалось сделать основные вещи, мне нужно передать данные обратно в Perl из подпрограмм C с использованием функций API Perl C.Проблемы возникают на этапе компиляции, когда я пишу подпрограмму сборщика C в исходном C под управлением Inline :: C.

Существуют конфликты символов, подобные этому: bind () определяется как в socket.h (Perl), так и в autoPilot.h (VTD-XML).Можно избежать конфликтов символов, создав VTD-XML как общую библиотеку с явной картой экспорта (gcc -Wl, -version-script = foo.map) ... Это правильный путь?Есть ли лучшие способы?

1 Ответ

4 голосов
/ 09 июня 2011

Я достиг своей цели, добавив слой косвенности: ужасно, как мне кажется, это работает.

Прежде всего, я создал общую библиотеку, содержащую API VTD-XML.Создавая этот общий объект, я должен был избежать загрязнения глобальной области видимости, экспортируя только необходимые символы.

Затем я создал другую общую библиотеку.Эта вторая общая библиотека скрывает API VTD-XML и должна использоваться из Perl через Inline :: C.В этом общем объекте я написал несколько функций, используя частично выставленный API libvtd.so.

Идея выглядит следующим образом:

Perl -> Inline::C dynamic loader -> wrapper_API.so -> libvtd.so 

Основные проблемы возникли из-за загрузки общих библиотек во время выполнения ииз столкновения / разрешения символов.

Вот как я собираю libvtd.so, упрощая использование так называемого wrapper_API.so.

К сожалению, VTD-XML не собираетсяlibvtd.so общий объект, поэтому мне пришлось создать его самостоятельно, связав вместе несколько объектных файлов .o с помощью gcc:

gcc -shared -fPIC -Wl,-soname,libvtd.so.2.10 -Wl,--version-script=vtd-xml.map \
-o libvtd.so.2.10 libvtd.o arrayList.o fastIntBuffer.o fastLongBuffer.o \
contextBuffer.o vtdNav.o vtdGen.o autoPilot.o XMLChar.o XMLModifier.o intHash.o \
 bookMark.o indexHandler.o transcoder.o elementFragmentNs.o

Видимость символа была настроена с помощью опции компоновщика -Wl,--version-script=vtd-xml.map, где файл карты был:

{
    global:
        the_exception_context;
        toString;
        getText;
        getCurrentIndex;
        toNormalizedString;
        toElement;
        toElement2;
        createVTDGen;
        setDoc;    
        parse;
        getNav;
        freeVTDGen;
        freeVTDNav;
        getTokenCount;
    local:
        *;  
};

Глобальные ("экспортированные") символы находятся в разделе global:, в то время как универсальный символ * в разделе local говорит о том, что все остальные символы известны только локально.

Все объектные модули происходят из дистрибутива VTD-XML, за исключением libvtd.o: этот пользовательский объект был необходим для решения проблем с библиотекой обработки исключений cexept.h.libvtd.c - это всего две строки кода.

#include "customTypes.h"
struct exception_context the_exception_context[ 1 ];

На этапе компиляции мне пришлось настроить CFLAGS для создания независимого от позиции кода (опция gcc -fPIC) для создания общих объектов. *Инструмент 1030 *

readelf был полезен для проверки видимости символов:

readelf --syms libvtd.so.2.10

Symbol table '.dynsym' contains 35 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
   ...
   280: 000000000000d010   117 FUNC    LOCAL  DEFAULT   12 writeIndex
   281: 000000000003c5d0   154 FUNC    LOCAL  DEFAULT   12 setCursorPosition
   282: 000000000003c1f0    56 FUNC    LOCAL  DEFAULT   12 resetIntHash
   ...
   331: 0000000000004f50  3545 FUNC    GLOBAL DEFAULT   12 toElement
   332: 00000000000071e0   224 FUNC    GLOBAL DEFAULT   12 getText
   333: 000000000000d420   114 FUNC    GLOBAL DEFAULT   12 freeVTDGen
   ...
   339: 000000000000b600   731 FUNC    GLOBAL DEFAULT   12 toElement2
   340: 000000000000e650   120 FUNC    GLOBAL DEFAULT   12 getNav
   341: 0000000000025750 70567 FUNC    GLOBAL DEFAULT   12 parse

Файл wrapperAPI.so состоит из нескольких функций, использующих API VTD-XML, его пользовательские типы., но принимать и возвращать только стандартные типы C и / или структуры.Оболочка пришла прямо из бывшей отдельной программы на Си.

...