Прямая обработка стека вызовов вызова [duplicate]

Чтобы преобразовать $date из dd-mm-yyyy hh:mm:ss в надлежащее MySQL-datetime, я иду так:

$date = DateTime::createFromFormat('d-m-Y H:i:s',$date)->format('Y-m-d H:i:s');
14
задан 21 revs 5 September 2012 в 00:48
поделиться

4 ответа

Я являюсь автором libffi. Он будет делать то, что вы просите.

5
ответ дан Anthony Green 28 August 2018 в 22:02
поделиться

@ Антти Хаапала указал на libffi . Вот некоторые сведения об этом:

Что такое libffi?

Некоторые программы могут не знать во время компиляции, какие аргументы должны быть переданы функции. Например, во время выполнения интерпретатору может быть рассказано о количестве и типах аргументов, используемых для вызова данной функции. «Libffi» может использоваться в таких программах, чтобы обеспечить мост от программы-интерпретатора до скомпилированного кода.

Библиотека libffi предоставляет портативный высокоуровневый программный интерфейс для различных соглашений вызова. Это позволяет программисту вызывать любую функцию, указанную в описании интерфейса вызова во время выполнения.

FFI означает интерфейс внешней функции. Интерфейс внешних функций - это популярное имя интерфейса, которое позволяет коду, написанному на одном языке, вызывать код, написанный на другом языке. Библиотека libffi действительно обеспечивает только самый низкий, зависящий от машины уровень полнофункционального интерфейса внешних функций. Уровень должен существовать над «libffi», который обрабатывает преобразования типов для значений, передаваемых между двумя языками.

«libffi» предполагает, что у вас есть указатель на функцию, которую вы хотите вызвать, и что вы знаете номер и типы аргументов для его передачи, а также возвращаемый тип функции.


Исторический фон

libffi, первоначально разработанный Энтони Грин (Пользователь SO: anthony-green ), был вдохновлен библиотекой Gencall от Silicon Graphics. Gencall был разработан Джанни Мариани, затем нанят SGI, чтобы разрешить вызовы функций по адресам и создать кадр вызова для конкретного соглашения о вызовах. Энтони Грин уточнил эту идею и распространил ее на другие архитектуры и вызывал соглашения и открывал источники libffi.


Вызов pow с libffi

#include <stdio.h>
#include <math.h>
#include <ffi.h>

int main()
{
  ffi_cif     call_interface;
  ffi_type    *ret_type;
  ffi_type    *arg_types[2];

  /* pow signature */
  ret_type = &ffi_type_double;
  arg_types[0] = &ffi_type_double;
  arg_types[1] = &ffi_type_double;

  /* prepare pow function call interface */
  if (ffi_prep_cif(&call_interface, FFI_DEFAULT_ABI, 2, ret_type, arg_types) == FFI_OK)
  {
    void *arg_values[2];
    double x, y, z;

    /* z stores the return */
    z = 0;

    /* arg_values elements point to actual arguments */
    arg_values[0] = &x;
    arg_values[1] = &y;

    x = 2;
    y = 3;

    /* call pow */
    ffi_call(&call_interface, FFI_FN(pow), &z, arg_values);

    /* 2^3=8 */
    printf("%.0f^%.0f=%.0f\n", x, y, z);
  }

  return 0;
}

Я думаю, что могу утверждать, что libffi - это переносимый способ делать то, что я просил, вопреки утверждению Антти Хаапалы о том, что такого пути нет. Если мы не можем назвать libffi переносимой технологией, учитывая, насколько она портирована / реализована в разных компиляторах и архитектурах, а какой интерфейс соответствует стандарту C, мы также не можем назвать C или что-нибудь портативное.

Информация и история извлечены из:

https://github.com/atgreen/libffi/blob/master/doc/libffi.info

http://en.wikipedia.org/wiki/Libffi

5
ответ дан 15 revs 28 August 2018 в 22:02
поделиться

Вы спросили, что такое переносимый способ вызвать любой указатель функции с заданным количеством аргументов. Правильный ответ заключается в том, что такого пути нет .

Например, python может вызывать функции C через модуль ctypes, но это переносимо только до тех пор, пока вы знаете точные прототипы и вызовы. В C самым простым способом добиться того же - знать прототип указателя функции во время компиляции.

Update

Для примера python / ctypes на каждой платформе, на которой включен модуль ctypes, python знает, как записать вызывающий стек для заданного набора аргументов. В Windows, например, python знает два стандартных соглашения о вызовах - cdecl с C параметрами порядка в стеке и stdcall с «упорядочением стиля pascal». В Linux необходимо беспокоиться о том, следует ли вызывать 32 или 64-битные общие объекты и т. Д. Если python скомпилирован на другую платформу, ctypes также нуждается в изменениях; C-код в модуле ctypes не является, как таковой, портативным.

Обновление 2

Для Python здесь находится волшебство: исходный код ctypes . В частности, похоже, что ссылка http://sourceware.org/libffi/ может быть именно тем, что вам нужно.

12
ответ дан Antti Haapala 28 August 2018 в 22:02
поделиться

Для обеспечения безопасности вы должны распаковать переменные до их отправки. Использование ассемблера для взлома стека параметров может быть несовместимым между компиляторами.

Я не могу говорить за Ruby, но я написал довольно много программ, используя интерфейсы C для Perl и Python. Переменные Perl и Python напрямую не сопоставляются с переменными C, у них есть еще много функций. Например, скаляр Perl может иметь двойные строковые и числовые значения, только один из которых действителен в любой момент времени.

Преобразование между Perl / Python-переменными и C выполняется с использованием pack и unpack (в модуле struct в Python). В интерфейсе C вы должны вызвать определенные API для выполнения преобразования, в зависимости от типа. Таким образом, это не просто прямая передача указателя, и это, конечно же, не связано с ассемблером.

2
ответ дан cdarke 28 August 2018 в 22:02
поделиться
Другие вопросы по тегам:

Похожие вопросы: