Изменить код через графический интерфейс - PullRequest
0 голосов
/ 17 января 2012

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

start %= -(status)
       >  lexeme[elementV]
       > -(lexeme[elementF])
       > +(inboundGroup);

Выше приведена часть моего кода Boost SPIRIT which parses Strings, так что, например, можно было бы изменить + на * or - и т. Д.

+ = One 
- = optional
* = multiple

Как вы думаете, было бы возможно изменить это через графический интерфейс, я думаю, что он просто не уверен, как это сделать?

Любая помощь, я буду очень признателен

Спасибо, Шамари

1 Ответ

1 голос
/ 18 января 2012

В программировании возможно все; -)

Для динамического изменения программы во время выполнения существует несколько решений:

  • Использование динамического языка, такого как LUA
  • Использование системы плагинов с динамической загрузкой

Поскольку вам требуются C ++ и Boost Spirit, я думаю, что лучшим решением будет создание плагина на лету и его загрузка впоследствии.

Ваша программа сгенерирует код, скомпилирует его в общую библиотеку (.so), а затем загрузит и выполнит его.(Некоторые люди найдут это грязным. Это также небезопасно. Но это просто и работает.)

Вот пример для linux: plugin.h :

#ifndef PLUGIN_H__
#define PLUGIN_H__

#ifdef __cplusplus
extern "C" {
#endif

int process();
typedef int (*plugin_process_fn_ptr)();

#ifdef __cplusplus
}
#endif

#endif // PLUGIN_H__

Обратите внимание, что мы должны использовать extern C или иначе, искажение имени C ++ затруднит импорт символов.

plugin.cpp :

#include "plugin.h"
#include <iostream>
using namespace std;

int process()
{
    int return_value = 0;

#include "plugin_content.inc.cpp"

    return return_value;
}

Обратите внимание, что здесь я использую хак, код будет включен из другого файла, "plugin_content.inc.cpp".Код от пользователя будет помещен внутрь.

скрипт для сборки плагина, "build_plugin.sh":

#! /bin/sh

g++ -c -Wall -fPIC plugin.cpp -o plugin.o
gcc -shared  -o libplugin.so   plugin.o

Теперь вызывающая программа, main.cpp :

#include <iostream>
#include <fstream> // to open files
#include <dlfcn.h> // C lib to load dynamic libs

#include "plugin.h"

using namespace std;

// load the plugin and call the process() function fom it
static int process_via_plugin()
{
    int return_value = -1;

    void *lib_handle(NULL);
    char *error(NULL);

    char *plugin_lib = "./libplugin.so";
    lib_handle = dlopen(plugin_lib, RTLD_LAZY);
    if (!lib_handle)
    {
        cerr << "Error loading lib " << plugin_lib << " : " << dlerror() << endl;
        exit(1);
    }

    char *plugin_fn = "process";
    plugin_process_fn_ptr fn = (plugin_process_fn_ptr)dlsym(lib_handle, plugin_fn);
    error = dlerror();
    if (error)
    {
        cerr << "Error finding lib " << plugin_fn << " : " << error << endl;
        exit(1);
    }

    // call the function loaded from lib
    return_value = (*fn)();

    dlclose(lib_handle);
    lib_handle = NULL; // useless but for good habits ^^

    return return_value;
}

// build or rebuild the plugin,
// we must call it when we change the plugin code code
static int build_plugin(string code)
{
    {
        char *plugin_code_file = "plugin_content.inc.cpp";

        ofstream plugin_code(plugin_code_file, ios::out);
        plugin_code << code << endl;
    }
    system("build_plugin.sh");

    return 0;
}

// our program
int main(int argc, char *argv[])
{
    cout << "Hello World !" << endl;

    string code = ""
"cout << \"Hello from plugin !\" << endl;"
"";

    // build a first version of the plugin and call it
    build_plugin(code);
    process_via_plugin();

    // now we modify the code (use a GUI here)
    code = ""
"cout << \"Hello from plugin, updated !\" << endl;"
"";
    // rebuild the plugin and call it again
    build_plugin(code);
    process_via_plugin();

    // do it again as much as you want.

    return 0;
}

Теперь соберите вашу программу:

g++ -Wall -rdynamic -ldl main.cpp

и выполните ее:

a.out

, и вы получите:

Hello World !
Hello from plugin !
Hello from plugin, updated !

Код, который я вам даю, очень простой.Например, мы должны проверить, успешна ли компиляция плагина, и сообщить пользователю об ошибках.Теперь вы можете добавить больше материала.

...