Я пытаюсь встроить библиотеку октав в более крупную программу. Требуется, чтобы я мог запускать и останавливать октавный интерпретатор по желанию из этой большой программы. Однако единственная функция, которая корректно останавливает интерпретатор октавы, также вызывает функцию exit(), которая также убивает большую программу. Библиотечная функция октавы — clean_up_and_exit().
В идеале я хотел бы вызвать только часть очистки (do_octave_atexit) и пропустить вызов для выхода.
Я пробовал следующее:
1) вызов do_octave_atexit, однако символ не экспортируется в библиотеку октавы. Я пытался получить к нему доступ в любом случае, но безрезультатно.
2) Я попытался подключиться к вызову выхода и заменить его функцией, которая не завершается, через ld_preload. Это все испортило, так как все остальные вызовы выхода также были перехвачены.
3) Я пытался определить, когда выход вызывается октавой, только для того, чтобы предотвратить это только тогда, обнаружив вызывающую функцию с вызовом обратной трассировки. Это по какой-то причине не показало, что я ожидаю от истинной иерархии вызовов. По какой-то причине он показал только основную функцию, а не содержимое иерархии вызовов через библиотеку октавы. Итак, не удалось обнаружить вызов, исходящий от октавы.
Код, который я использую для вызова функций октавы, выглядит так:
//
// Octave Setup Functions
//
extern "C" void oct_init (const char * path) {
string_vector argv (2);
argv(0) = "embedded";
argv(1) = "-q";
octave_main (2, argv.c_str_vec (), 1);
if(strlen(path) > 1) {
oct_addpath(path);
}
}
extern "C" void oct_exit (void) {
printf("Exiting!");
clean_up_and_exit (1,1);
}
Ключевой функцией здесь является clean_up_and_exit, которая реализована в исходном коде октавы как:
void clean_up_and_exit (int retval, bool safe_to_return)
{
do_octave_atexit ();
if (octave_link::exit (retval))
{
if (safe_to_return)
return;
else
{
gnulib::sleep (86400);
}
}
else
{
if (octave_exit)
(*octave_exit) (retval);
}
}
Таким образом, приведенный выше код вызывает функцию, которую я хочу (do_octave_atexit), но затем переходит к вызову *octave_exit, который является указателем функции на exit().
В идеале я хочу либо а) предотвратить этот вызов exit(), либо б) перехватить вызов, когда он исходит только из октавы, и предотвратить его, и разрешить его, когда он исходит из других источников. Я не смог сделать а) или б) до сих пор!
Так что на данный момент у меня нет идей. Я мог бы перекомпилировать октаву, но это решение должно работать со стандартной установкой октавы.
Это должно было работать только в среде linux/gcc.
Любые и все предложения по этому очень сложному вопросу с благодарностью.