Как обеспечить js-ctypes во вложении spidermonkey? - PullRequest
1 голос
/ 27 февраля 2012

Резюме

Я просмотрел код, который приложение оболочки 'SpiderMonkey использует для создания JavaScript-объекта ctypes, но я начинающий программист на Си. Из-за различных уровней безумия, испускаемых современными системами сборки, я не могу отследить код или команду, которая фактически связывает программу с желаемой функциональностью.


method.madness

Эта реализация js-ctypes от The Mozilla Devs является отличным дополнением. С момента своего создания сценарии в основном использовались для обеспечения контроля над более строгими и надежными приложениями. Появление js-ctypes в проекте SpiderMonkey позволяет JavaScript встать на ноги и считаться полноценным объектно-ориентированным языком быстрой разработки приложений, который поднимается над «планкой», установленной различными почтенными языками разработки приложений, такими как Microsoft VB6.


Должны ли мы начать?

Я собрал SpiderMonkey с этой конфигурацией: ./configure --enable-ctypes --with-system-nspr

с последующим успешным выполнением: make && make install

Оболочка js работает нормально, и в этой оболочке была проверена работоспособность глобального объекта javascript ctypes.

Работая с кодом, взятым из первого списка источников на Как встроить JavaScript Engine -MDN , я попытался создать экземпляр объекта JavaScript ctypes, вставив следующий код в строку 66:

    /* Populate the global object with the ctypes object. */
    if (!JS_InitCTypesClass(cx, global))
        return NULL;
    /*

Я скомпилировал с помощью: g ++ $ (./ js-config --cflags --libs) hello.cpp -o hello

Он компилируется с несколькими предупреждениями:

hello.cpp: In function ‘int main(int, const char**)’:
hello.cpp:69:16: warning: converting to non-pointer type ‘int’ from NULL [-Wconversion-null]
hello.cpp:80:20: warning: deprecated conversion from string constant to ‘char*’ [-Wwrite-strings]
hello.cpp:89:17: warning: NULL used in arithmetic [-Wpointer-arith]

Но при запуске приложения:

./hello: symbol lookup error: ./hello: undefined symbol: JS_InitCTypesClass

Более того

JS_InitCTypesClass объявлен extern в 'dist / include / jsapi.h', но функция находится в 'ctypes / CTypes.cpp', который включает в себя собственный заголовок 'CTypes.h' и в какой-то момент компилируется некоторой командой во время 'make' to yeild './CTypes.o'. Как я уже говорил ранее, я менее чем новичок с кодом C, и я действительно не знаю, что здесь делать.

Пожалуйста, дайте или дайте указание на общий пример того, как сделать объект js-ctypes функциональным во встраивании.

Ответы [ 2 ]

1 голос
/ 31 марта 2012

Проблема: большинство распространителей платформ не знают рекомендаций, данных разработчиками кода.Поэтому js-ctypes не включены для mozjs185 в большинстве, если не во всех системах, где размещена библиотека.Это оставляет некоторые проблемы для вас, чтобы разобраться.

После того, как вы настроили с помощью --enable-ctypes и --with-sytem-nspr, затем make и затем make install (может потребоваться rootдля последней команды)

Скорее всего, в вашей системе будет две версии libmozjs185.so.Один с включенным ctypes (находится в / usr / local / lib), а другой без включенного ctypes (находится в /usr/lib).

Вы, по вопросу, хотите связать библиотеку с типами.Вот что вы делаете, указав: -L/usr/local/lib -lnspr4 -lmozjs185 вашему компилятору.Это скомпилируется нормально.Но когда приложение запускается, загрузчик библиотеки os загрузит первый экземпляр библиотеки, который он найдет.К сожалению, это, вероятно, будет библиотека, расположенная в / usr / lib, и в этой версии, вероятно, не включен ctypes.Вот где вы столкнетесь с этой [решенной] проблемой: g ++ Неопределенный символ Ошибка при использовании общей библиотеки

Суть в следующем: несколько версий одной и той же библиотеки создают один адвопрос.Поэтому лучший способ предоставить js-ctypes для встраивания spidermonkey - это связать статическую версию mozjs185 с включенной ctypes с вашей программой, если только вы не хотите написать библиотеку для работы с несколькими загрузчиками платформы на платформе или создать свою собственную (ребрендовую версию mozjs185).), о котором я подробно рассказал в @ Документация по сборке SpiderMonkey - MDN

Для выполнения статической компоновки вам нужно будет использовать эти параметры с g ++: -lnspr4 -lpthread -lmozjs185-1.0 при условии, что вы создалии правильно установил пакет разработки.Это лучший (независимый от платформы) способ предоставления js-ctypes для встраивания spidermonkey.Хотя это увеличивает размер вашего приложения как минимум на 3,5 МБ.Если вы создали отладочную версию, она может быть больше, чем в 15 раз.

1 голос
/ 27 февраля 2012

Взлом

Мне уже приходило в голову, что связывание не выполняется из-за условных определений в заголовочных файлах, а также из-за разбросанных lib и местоположений заголовков. Достаточно хорошо ... Я попытался определить JS_HAS_CTYPES в командной строке, но если он вообще работал, этого явно было недостаточно.

Я решил, что поскольку оболочка SpiderMonkey имеет свой собственный уникальный make-файл и уже имеет рабочий доступ к функциям, которые я пытаюсь перехватить, просто переименуйте js.cpp в js.cpp.tmp и разрешите моему коду стоять на своем месте. , почти сработало.

Файл скомпилирован хорошо, и при выполнении приложения не возникало ошибок компоновки во время выполнения, но код (ctypes 'JSNativeObject') почти полностью завершился ошибкой JS_InitCTypesClass. Видя, что моя ошибка компоновки давно забыта, я сразу же просмотрел вывод команды make, чтобы посмотреть, смогу ли я «пролистать» код компиляции и ... У нас есть БИНГО!


Компиляция

После восстановления shell / js.cpp до его первоначальной цели я переместил hello.cpp в корневой каталог spidermonkey и начал исправлять относительные пути, созданные make-файлом, а также выполнил удаление конструкций, которые очевидно, не имел никакого отношения к моей заявке.

Хотя следующие команды, по-видимому, отображают операционный двоичный файл, автор не может дать сродства относительно правильности или полноты этого списка.

c++ -o hello.o -c  -Idist/system_wrappers_js -include config/gcc_hidden.h \
-DEXPORT_JS_API -DOSTYPE=\"Linux3.2\" -DOSARCH=Linux -I. -Idist/include \
-Idist/include/nsprpub  -I/usr/include/nspr -fPIC  -fno-rtti \
-fno-exceptions -Wall -Wpointer-arith -Woverloaded-virtual -Wsynth \
-Wno-ctor-dtor-privacy -Wno-non-virtual-dtor -Wcast-align \
-Wno-invalid-offsetof -Wno-variadic-macros -Werror=return-type -pedantic \
-Wno-long-long -fno-strict-aliasing -pthread -pipe  -DNDEBUG -DTRIMMED -Os \
-freorder-blocks -fomit-frame-pointer -DJS_HAS_CTYPES -DMOZILLA_CLIENT \
-include js-confdefs.h -MD -MF .deps/hello.pp hello.cpp;

c++ -o hello -fno-rtti -fno-exceptions -Wall -Wpointer-arith \
-Woverloaded-virtual -Wsynth -Wno-ctor-dtor-privacy \
-Wno-non-virtual-dtor -Wcast-align -Wno-invalid-offsetof \
-Wno-variadic-macros -Werror=return-type -pedantic \
-Wno-long-long -fno-strict-aliasing -pthread -pipe  -DNDEBUG \
-DTRIMMED -Os -freorder-blocks -fomit-frame-pointer hello.o \
-lpthread -Wl,-rpath-link,/bin -Wl,-rpath-link,/usr/local/lib \
-Ldist/bin -Ldist/lib -L/usr/lib -lplds4 -lplc4 -lnspr4 \
-lpthread -ldl editline/libeditline.a libjs_static.a -ldl;

Две команды, перечисленные выше, были помещены в исполняемый скрипт оболочки с именем 'mkhello', который был сохранен в корневом каталоге исходного кода.

Из того, что я могу собрать, это двухэтапный метод компиляции. По какой причине я не уверен, но объяснение кажется очень познавательным. Мысли?

РЕДАКТИРОВАТЬ см. Комментарий ниже для объяснения "двухэтапного метода компиляции".


Код: hello.cpp

/*
 * This define is for Windows only, it is a work-around for bug 661663.
 */
#ifdef _MSC_VER
# define XP_WIN
#endif

/* Include the JSAPI header file to get access to SpiderMonkey. */
#include "jsapi.h"


/* The class of the global object. */
static JSClass global_class = {
    "global", JSCLASS_GLOBAL_FLAGS,
    JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_StrictPropertyStub,
    JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub,
    JSCLASS_NO_OPTIONAL_MEMBERS
};

/* The error reporter callback. */
void reportError(JSContext *cx, const char *message, JSErrorReport *report)
{
    fprintf(stderr, "%s:%u:%s\n",
            report->filename ? report->filename : "<no filename=\"filename\">",
            (unsigned int) report->lineno,
            message);
}

int main(int argc, const char *argv[])
{
    /* JSAPI variables. */
    JSRuntime *rt;
    JSContext *cx;
    JSObject  *global;

    /* Create a JS runtime. You always need at least one runtime per process. */
    rt = JS_NewRuntime(8 * 1024 * 1024);
    if (rt == NULL)
        return 1;

    /* 
     * Create a context. You always need a context per thread.
     * Note that this program is not multi-threaded.
     */
    cx = JS_NewContext(rt, 8192);
    if (cx == NULL)
        return 1;
    JS_SetOptions(cx, JSOPTION_VAROBJFIX | JSOPTION_JIT | JSOPTION_METHODJIT);
    JS_SetVersion(cx, JSVERSION_LATEST);
    JS_SetErrorReporter(cx, reportError);

    /*
     * Create the global object in a new compartment.
     * You always need a global object per context.
     */
    global = JS_NewCompartmentAndGlobalObject(cx, &global_class, NULL);
    if (global == NULL)
        return 1;

    /*
     * Populate the global object with the standard JavaScript
     * function and object classes, such as Object, Array, Date.
     */
    if (!JS_InitStandardClasses(cx, global))
        return 1;

    /* Populate the global object with the ctypes object. */
    if (!JS_InitCTypesClass(cx, global))
        return NULL;
    /*

    /* Your application code here. This may include JSAPI calls
     * to create your own custom JavaScript objects and to run scripts.
     *
     * The following example code creates a literal JavaScript script,
     * evaluates it, and prints the result to stdout.
     *
     * Errors are conventionally saved in a JSBool variable named ok.
     */
    char *script = "ctypes.open";
    jsval rval;
    JSString *str;
    JSBool ok;
    const char *filename = "noname";
    uintN lineno = 0;

    ok = JS_EvaluateScript(cx, global, script, strlen(script),
                           filename, lineno, &rval);
    if (rval == NULL | rval == JS_FALSE)
        return 1;

    str = JS_ValueToString(cx, rval);
    printf("%s\n", JS_EncodeString(cx, str));

    /* End of your application code */

    /* Clean things up and shut down SpiderMonkey. */
    JS_DestroyContext(cx);
    JS_DestroyRuntime(rt);
    JS_ShutDown();
    return 0;
}

Заключение

$ ./mkhello
# ...
# error free garbage scrolls....
$ ./hello
function open() {
    [native code]
}

Следуйте этому примеру, чтобы предоставить js-ctypes для встраивания SpiderMonkey. Вам может понадобиться, а может и нет, пересоздать эти шаги по порядку, но это настоятельно рекомендуется с моей текущей точки зрения.

...