среда, 19 июня 2013 г.

Откуда ждать подлянки...

... или Знаете ли вы что...

Кросспост из ЖЖ. Оригинал находится тут.

Инфоповод: Компания Oracle молча перевела man-руководства MySQL на проприетарную лицензию. О чем это нам говорит? О том, что у Oracle были права на эти руководства, несмотря на GPL. Скорее всего, так вышло, потому что документацию писали сотрудники на зарплате, а не сообщество, но я сейчас не об этом.

Гораздо интересней то, что в ряде проектов с двойным лицензированием используется практика передачи прав на код при попадании в апстрим. Так было, например, в OpenOffice.org до передачи его в Апач. Почему-то мало кто задумывается, что от закрытия кода только с одной стороны защищает GPL, а с другой — наличие множества независимых владельцев прав на этот код, которых одновременно уговорить на смену лицензии вряд ли получится. Для end-user проектов это не особо критично, поскольку уже опубликованную под GPL версию закрыть не получится, а вот для инфраструктурных, в которых важен весь жизненный цикл, обновения, вот это всё... В общем, лучше на такое не завязываться бы.

А теперь собственно, зачем этот пост. Практика отъема прав у разработчиков существует не где-нибудь, а в Проекте GNU, да благословит его Аллах и приветствует.

Можно возразить, что уж кто-кто, а FSF свободу ПО ущемлять не будет, но не всё так просто. Во-первых, где гарантия, что вместо фанатичных, но всё же вменяемых, гиков к руководству фондом не придут какие-нибудь упоротые и не забабахают неприемлемую для зависимых проектов, а главное — несовместимую с приемлемыми, новую лицензию? Во-вторых, где гарантия, что по глупости, или злому умыслу, FSF внезапно не случится банкротом, и его «интеллектуальная собственность» не пойдет с молотка?

суббота, 8 июня 2013 г.

Чего-то я не понимаю в этом вашем rb_protect...

Сначала маленькое неприятное, но понятное наблюдение: rb_eval_string_protect() в Ruby 1.9 (и, надо полагать, в 2.0 тоже) воспринимает эту самую «string» как содержащую данные в кодировке US-ASCII. Собственно, так поступают все фунции работы со строками, унаследованные из 1.8, но для обычного преобразования строки в ruby-объект String есть новые функции, позволяющие кодировку указать. А для rb_eval_string_protect() соответствующих аналогов не предусмотрено...

Отсюда логичное желание сначала строку преобразовать (с указанием правильной UTF-8), а затем уже выполнить — скормить методу Kernel.eval(). Заворачиваем этот вызов в функцию, вызываем ее через rb_protect()... И получаем странную вещь — все вроде бы отрабатывается, но если в Ruby происходит исключение, рушится стек исключений уже внешнего pascal-кода. При успешном вызове такого не происходит. Возможно, где-то косяк с соглашениями о вызове — си-паскаль переходы штука тонкая, да... Но: а) любые действия, не вызывающие исключения, проходят на ура, многократно и т.д., т.е. стек вызовов, в отличие от стека исключений, в порядке, и б) ruby-методы, мною созданные из pascal-функций, с теми же соглашениями о вызовах, работают правильно...

Причем, rb_eval_string_protect() работает прекрасно — корректно обрабатывает исключения, как и должно быть по документации. Только о кодировках ничего не знает, а так — ok. В общем, сейчас рабочий вариант такой — задаю глобальную переменную «$script_string», а затем через rb_eval_string_protect() выполняю «eval $script_string». Само по себе это решение меня устраивает, но непонятки с rb_protect() все-таки напрягают.

PS. Для иллюстрации: проблемный код vs беспроблемный код.

среда, 5 июня 2013 г.

Маленький нюанс MethodAddress

Иногда во Free Pascal / Lazarus бывает нужно динамически устанавливать обработчики событий — имеем объект и имя свойства-события и устанавливаем через SetMethodProp(). В ряде мест можно встретить инструкции делать примерно так:

var
  meth : TMethod;
. . . . .
meth.Data = MyHandlerObject;
meth.Code = MyHandlerObject.MethodAddress('HandlerMethod');
SetMethodProp(Reciever, 'onEvent', meth);

А оно не работает. Потому, например, что HandlerMethod() невиртуальный. В общем, не надо тут усложнять, если имя метода известно при компиляции. Всё просто:

SetMethodProp(Receiver, 'onEvent', TMethod(@MyHandlerObject.HandlerMethod));

понедельник, 3 июня 2013 г.

Экую интересную багофичу поймал...

Занимаясь переработкой ppRuby, напоролся на очень интересную особенность, которая стоила мне часов восьми матерной отладки...

Вкратце: в одном из определяемых методов заворачивал я объекты (дочерние компоненты) в объекты Ruby, складывал в массив, затем — преобразовывал массив в рубишный посредством “rb_ary_new4()”. При дальнейшем использовании этого массива получал AV. При этом формирование хэша, перебор этих дочерних компонентов, и т.д., и т.п. — всё проходило прекрасно. А с массивом — жопа.

В итоге выяснилось следующее: пока добавлялись последние элементы, по первым успевал пройтись сборщик мусора — у движка-то на них ссылок не было... Решение: создавать пустой массив и добавлять по одному. Работает.