Форум программистов, компьютерный форум CyberForum.ru
Наши страницы

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
 
Рейтинг: Рейтинг темы: голосов - 12, средняя оценка - 4.67
vlinx
1 / 1 / 0
Регистрация: 27.06.2014
Сообщений: 74
#1

Компиляция исходного кода в работающей программе - C++

07.07.2014, 16:21. Просмотров 1570. Ответов 47
Метки нет (Все метки)

Привет.

Подскажите, как можно скомпилировать код, и использовать полученный результат в запущенной программе, если этот самый код находится, в компоненте (memo, list итд - неважно) этой запущенной пргораммы.

Я нашел 1 вариант - это сохранение этого кода в файл и компиляция в отдельном процессе.
Это правильный вариант? и есть ли еще пути решения?
0
Лучшие ответы (1)
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
07.07.2014, 16:21
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Компиляция исходного кода в работающей программе (C++):

Загрузка исходного кода и компиляция *.exe - C++
Помогите разобраться как в Visual Studio 2010 загрузить исходный код для компиляции программы?

Компиляция исходного кода C++ ubuntu если нет компилятора g++ - C++
как запустить кода C++ в ubuntu если нет компилятора g++. код набран в текстовых файлах main.cpp func.cpp f.cpp func.h f.h в...

Исправить ошибку в программе, работающей с дробями - C++
#include <iostream> using namespace std; int main(){ int a,b,c,d,e,f; cout << "Введите первую дробь:/n"; cin >> a >> "/" >> b;...

Компиляция кода в приложении - C++
Можно каким-либо образом скомпилировать код в работающем приложении. Т.е. приложение работает, в него подается файл с исходным кодом, его...

Компиляция кода Freeglut - C++
Здравствуйте. Стоит Ubuntu 12.10, компилятор g++ , библиотеку freeglut поставил из репозитория, после чего инклуды появились нужном месте в...

Компиляция кода в командной строке - C++
на паре нам показывали как работать с прогой, написанной на ассемблере - cmd-> выбор директории -> создание объектного файла с помощью...

Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
vlinx
1 / 1 / 0
Регистрация: 27.06.2014
Сообщений: 74
08.07.2014, 17:18  [ТС] #31
давненько уже гадал откуда же беруться всякие кракозябры типа _ZN9wikipedia7article8print_toERSo
0
DrOffset
7152 / 4293 / 968
Регистрация: 30.01.2014
Сообщений: 7,093
08.07.2014, 17:19 #32
Цитата Сообщение от vlinx Посмотреть сообщение
можно опять делать парсинг input_memo_text и считать кол-во и типы параметров и рез-тат ф-ии.
Безопаснее было бы ограничить пользователя определенным контрактом. Т.е. не разрешать ему использовать абсолютно любые параметры функции, а только определенных типов и ограниченное количество. Либо реализовать свой стек для параметров, как это сделано, например, в lua. Но это уже шаг в сторону интерпретаторов. А тут проще заюзать готовый
0
vlinx
1 / 1 / 0
Регистрация: 27.06.2014
Сообщений: 74
09.07.2014, 21:12  [ТС] #33
Цитата Сообщение от DrOffset Посмотреть сообщение
А тут проще заюзать готовый
тобишь вариант 4?

я его реализую тоже, но сначала этот до конца доведу.

Добавлено через 22 часа 21 минуту
Реализация варианта 3 (создание процесса с генерацией dll по шаблону) получилась следующая:
так как эта функция(возможность компиляции пользовательского кода) часть приложения, код в стиле ООП.

cAlgorithmGen.h
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
#ifndef CALGORITHMGEN_H
#define CALGORITHMGEN_H
 
#include <windows.h>
#include <TCHAR.H>
#include <sstream>
#include <iostream>
#include <fstream>
#include <string>
 
//генерация данных по
//пользовательскому алгоритму
class cAlgorithmGen //:public cUserGen //:public IGenerator
{
public:
 
    cAlgorithmGen(const std::string& memo_text,
                  const std::string& dll_name,
                  const std::string& workspace,
                  const std::string& compiler_path);
 
    ~cAlgorithmGen();
 
public:
    std::string next_value( int param1 = 0,
                            int param2 = 0,
                            int param3 = 0,
                            int param4 = 0,
                            const std::string& param5 = "null");
 
private:
    cAlgorithmGen();
 
    void prepare_files();
    void compile_dll();
 
    std::string get_declaration();
    std::string get_definition();
 
    std::string int2str(int x);
 
private:
    HINSTANCE h;
    int (*func_from_dll) (int, int, int, int, const std::string&);
    std::string m_memo_text;
    std::string m_dll_name;
    std::string m_workspace;
    std::string m_compiler_path;
};
 
#endif // CALGORITHMGEN_H

cAlgorithmGen.cpp
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
#include "cAlgorithmGen.h"
 
 
/*
cAlgorithmGen::cAlgorithmGen()
    :m_memo_text(""),
     m_dll_name(""),
     m_workspace(""),
     m_compiler_path("")
{
 
}
*/
 
 
cAlgorithmGen::cAlgorithmGen(const std::string& memo_text,
                             const std::string& dll_name,
                             const std::string& workspace,
                             const std::string& compiler_path)
    :h(0),
     func_from_dll(0),
     m_memo_text(memo_text),
     m_dll_name(dll_name),
     m_workspace(workspace),
     m_compiler_path(compiler_path)
{
    prepare_files();
    compile_dll();
 
 
    std::string dll_full_path = m_workspace + m_dll_name + ".dll";
 
    //подгружаем  dll
    h = LoadLibrary(dll_full_path.c_str());
    if (!h)
    {
        std::cerr<< "dll not found\n";
        return;
    }
 
    //call function from dll
    func_from_dll = (int (*) (int, int, int, int, const std::string&)) GetProcAddress(h, "main"); //dependence2
 
    if (!func_from_dll)
    {
        std::cerr << "function not found\n";
        return;
    }
}
 
 
cAlgorithmGen::~cAlgorithmGen()
{
    FreeLibrary(h);
 
    h = 0;
    func_from_dll = 0;
}
 
 
 
std::string cAlgorithmGen::next_value(int param1,
                                      int param2,
                                      int param3,
                                      int param4,
                                      const std::string& param5)
{
    int generated_value = func_from_dll(param1,
                                        param2,
                                        param3,
                                        param4,
                                        param5); //dependence3
 
    return int2str(generated_value);
}
 
 
 
void cAlgorithmGen::prepare_files()
{
    //Сохранение кода в файлы .h .cpp для компиляции DLL
 
    std::ofstream dll_h;
    dll_h.open((m_workspace + m_dll_name + ".h").c_str(), std::ios::out);
 
    dll_h <<"#ifndef EXAMPLE_DLL_H\n" //fix
            "#define EXAMPLE_DLL_H\n"
            "#ifdef __cplusplus\n"
            "extern \"C\" {\n"
            "#endif\n"
            "#ifdef BUILDING_EXAMPLE_DLL\n"
            "#define EXAMPLE_DLL __declspec(dllexport)\n"
            "#else\n"
            "#define EXAMPLE_DLL __declspec(dllimport)\n"
            "#endif\n"
            << get_declaration() << "\n"
            <<"#ifdef __cplusplus\n"
            "}\n"
            "#endif\n"
            "#endif\n";
 
    dll_h.close();
 
 
 
    std::ofstream dll_cpp;
    dll_cpp.open((m_workspace + m_dll_name + ".cpp").c_str(), std::ios::out);
 
    dll_cpp << "#include <iostream>" << std::endl;
    dll_cpp << "#include \"" + m_dll_name + ".h\"\n";
    dll_cpp << get_definition() << "\n";
    dll_cpp.close();
}
 
 
void cAlgorithmGen::compile_dll()
{
    STARTUPINFO startupInfo;
    PROCESS_INFORMATION processInformation;
 
    memset(&processInformation, 0, sizeof(processInformation));
    memset(&startupInfo, 0, sizeof(startupInfo));
    startupInfo.cb = sizeof(startupInfo);
 
 
 
    std::string c1 = m_compiler_path + " " + "-c -DBUILDING_EXAMPLE_DLL" + " " + m_workspace + m_dll_name + ".cpp" + " -o " + m_workspace + m_dll_name + ".o";
    TCHAR *czCommandLine1 = new TCHAR[c1.size() + 1]; //TCHAR - макрос, для независимости от кодировок
    czCommandLine1[c1.size()] = 0;
    std::copy(c1.begin(), c1.end(), czCommandLine1);
 
    CreateProcess(NULL, czCommandLine1, NULL, NULL, FALSE, 0, NULL, NULL, &startupInfo, &processInformation);
    WaitForSingleObject(processInformation.hProcess, INFINITE);
 
 
 
    std::string c2 = m_compiler_path + " " + "-shared -o " + m_workspace + m_dll_name + ".dll " + m_workspace + m_dll_name + ".o -Wl,--out-implib," + m_workspace + "libexample_dll.a";
    TCHAR *czCommandLine2 = new TCHAR[c2.size() + 1];
    czCommandLine2[c2.size()] = 0;
    std::copy(c2.begin(), c2.end(), czCommandLine2);
 
    CreateProcess(NULL, czCommandLine2, NULL, NULL, FALSE, 0, NULL, NULL, &startupInfo, &processInformation);
    WaitForSingleObject(processInformation.hProcess, INFINITE);
 
 
    CloseHandle(processInformation.hProcess);
    CloseHandle(processInformation.hThread);
 
    delete czCommandLine1;
    delete czCommandLine2;
}
 
 
std::string cAlgorithmGen::get_declaration()
{
    std::size_t end_declaration_pos = m_memo_text.find_first_of(")");
    std::string declaration = m_memo_text.substr(0, end_declaration_pos + 1) + ";";
    std::cout << "DECL: " << declaration << "\n";
 
    return declaration;
 
}
 
 
std::string cAlgorithmGen::get_definition()
{
    std::size_t end_declaration_pos = m_memo_text.find("main");
    std::string definition = m_memo_text.substr(end_declaration_pos - 4, m_memo_text.size() - 1);
    std::cout << "DEFF: " << definition << "\n";
 
    return definition;
}
 
 
std::string cAlgorithmGen::int2str(int x)
{
    std::ostringstream result;
    result << x;
    return result.str();
}


Допустим в приложении(в моем) нет нужного генератора данных, и нужно задать свои правила генерации определенных значений.
Например:
-Сгенерировать 10 значений начиная с "0" с шагом 3, и вывести на экран\файл.

Для этой цели использование класса будет следующим:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#include "cAlgorithmGen.h"
 
using namespace std;
 
int main()
{
    /************************input data*********************************************/
 
    std::string compiler_path = "C:\\strawberry\\c\\bin\\g++";
    std::string dll_name = "example_dll";
    std::string workspace = "D:\\test_dll_ias\\";
 
    //Загрузка в строку введенного пользователем кода
    //std::string input_memo_text = "int get_my_inn(int x, int y){ int z = 4; return x * y - z; }";
    std::string input_memo_text = "static int kk = 0; int main(int x1, int x2, int x3, int x4, const std::string&){ int tmp = kk + x1;kk += x2; return tmp;}";
 
    /************************create data generator**********************************/
 
    cAlgorithmGen* gena1 = new cAlgorithmGen(input_memo_text,
                                             dll_name,
                                             workspace,
                                             compiler_path);
 
 
    /************************start data generator***********************************/
 
    int start_value = 0;
    int step = 3;
 
    for(int i = 0; i < 10; ++i)
    {
        std::cout << gena1->next_value(start_value, step) << "\n";
    }
 
 
    delete gena1;
    gena1 = 0;
 
    return 0;
}
Получаем значения: 0,3,6,9..27, которые уже можем использовать где требуется.



При такой реализации оснавная проблема - в зависимости шаблона прототипа функции в dll и прототипа вызова ф-ии в коде. Они должны совпадать.
Здесь решил использовать только 1 шаблон:
C++
1
int (*func_from_dll) (int, int, int, int, const std::string&);
тем самым предоставив пользователю 5 параметров. Можно использовать любой на выбор. Это накладывает ограничение на прототип ф-ии, который пользователь введет в поле MEMO - прототип будет всегда такой.

За генерацию следующего конкретного значения на каждом цикле генератора отвечает метод
C++
1
next_value()
это обертка для вызова ф-ии dll с аргументами по умолчанию. Аргументы по умолчанию введены - для удобства использования только нужного кол-ва параметров из 5 предложенных.

Добавлено через 5 часов 23 минуты
оказывается LoadLibrary нужно передавать unicode-строку

нужно заменить кусок на

C++
1
2
3
4
5
    std::string dll_full_path = m_workspace + m_dll_name + ".dll";
    std::wstring w_dll_full_path = std::wstring(dll_full_path.begin(), dll_full_path.end());
 
    //подгружаем  dll
    h = LoadLibrary(w_dll_full_path.c_str());
0
DrOffset
7152 / 4293 / 968
Регистрация: 30.01.2014
Сообщений: 7,093
09.07.2014, 21:17 #34
Цитата Сообщение от vlinx Посмотреть сообщение
оказывается LoadLibrary нужно передавать unicode-строку
Это зависит от настроек. Можно и явно вызвать LoadLibraryA.
Для указания wchar_t строковых литералов, используется префикс L.
C++
1
L"some text"
Это чтобы избежать переливания строк из char в wchar_t, которые я у тебя наблюдаю
0
vlinx
1 / 1 / 0
Регистрация: 27.06.2014
Сообщений: 74
09.07.2014, 22:08  [ТС] #35
Цитата Сообщение от DrOffset Посмотреть сообщение
Для указания wchar_t строковых литералов, используется префикс L.
но в этом случае
C++
1
std::string dll_full_path = m_workspace + m_dll_name + ".dll";
префикс L не вставить

Добавлено через 20 минут
Цитата Сообщение от DrOffset Посмотреть сообщение
Это чтобы избежать переливания строк из char в wchar_t, которые я у тебя наблюдаю
DrOffset, а где строки char? я вроде их вообще стараюсь не использовать в коде, а вместо них std::string всегда пользую. Хотя std::strin это обертка над char, но все же это не char. Так?
0
DrOffset
7152 / 4293 / 968
Регистрация: 30.01.2014
Сообщений: 7,093
09.07.2014, 22:25 #36
vlinx, std::string типизирован типом char. А std::wstring - типом wchar_t. Это я и имел в виду под строками char
Это тайпдефы.
C++
1
2
 typedef basic_string<char>    string;
 typedef basic_string<wchar_t> wstring;
Если бы я говорил о char массивах с нулем на конце, то я сказал бы "C-style string"

Цитата Сообщение от vlinx Посмотреть сообщение
префикс L не вставить
Я предлагаю вообще не использовать std::string, а сразу std::wstring.
1
vlinx
1 / 1 / 0
Регистрация: 27.06.2014
Сообщений: 74
09.07.2014, 22:32  [ТС] #37
Цитата Сообщение от DrOffset Посмотреть сообщение
Это тайпдефы.
про тайпдефы знаю.
ясно, спасибо

Добавлено через 1 минуту
Цитата Сообщение от DrOffset Посмотреть сообщение
Я предлагаю вообще не использовать std::string, а сразу std::wstring.
в данном случае или вообще всегда, в любых приложениях?
0
DrOffset
7152 / 4293 / 968
Регистрация: 30.01.2014
Сообщений: 7,093
09.07.2014, 22:36 #38
Цитата Сообщение от vlinx Посмотреть сообщение
в данном случае или вообще всегда, в любых приложениях?
В приложениях для win(API) По той причине, что WinAPI нативно поддерживает wchar_t (UCS-2) (если не совру, то с версии NT), а ansi версии функций обеспечиваются через слой совместимости.
0
vlinx
1 / 1 / 0
Регистрация: 27.06.2014
Сообщений: 74
09.07.2014, 22:46  [ТС] #39
как то с wstring трудно работается.

C++
1
std::wstring m_workspace = "werwer";
-нельзя

C++
1
std::wstring m_dll_name = "werwer2";
-нельзя

как такую строку можно получить вообще?)
C++
1
 std::wstring w_dll_full_path = m_workspace + m_dll_name + ".dll";
0
DrOffset
7152 / 4293 / 968
Регистрация: 30.01.2014
Сообщений: 7,093
09.07.2014, 22:48 #40
Цитата Сообщение от vlinx Посмотреть сообщение
std::wstring m_workspace = "werwer";
А так?
C++
1
std::wstring m_workspace = L"werwer";
0
vlinx
1 / 1 / 0
Регистрация: 27.06.2014
Сообщений: 74
09.07.2014, 22:49  [ТС] #41
а если "werwer" передается через параметр?
0
DrOffset
7152 / 4293 / 968
Регистрация: 30.01.2014
Сообщений: 7,093
09.07.2014, 22:53 #42
Цитата Сообщение от vlinx Посмотреть сообщение
как такую строку можно получить вообще?
C++
1
2
3
4
5
6
7
std::wstring compiler_path = L"C:\\strawberry\\c\\bin\\g++";
std::wstring dll_name = L"example_dll";
std::wstring workspace = L"D:\\test_dll_ias\\";
 
std::wstring w_dll_full_path = workspace + dll_name + L".dll";
 
h = LoadLibrary(w_dll_full_path.c_str());
Добавлено через 38 секунд
Цитата Сообщение от vlinx Посмотреть сообщение
а если "werwer" передается через параметр?
Через какой?
1
vlinx
1 / 1 / 0
Регистрация: 27.06.2014
Сообщений: 74
09.07.2014, 22:56  [ТС] #43
Цитата Сообщение от DrOffset Посмотреть сообщение
Через какой?
C++
1
2
3
4
5
std::wstring func(std::wstring p1, std::wstring p2)
{
     std::wstring res = p1 + p2 + ".dll";
    return res;
}
Добавлено через 1 минуту
а, я кажется подустал)
все понятно
0
DrOffset
7152 / 4293 / 968
Регистрация: 30.01.2014
Сообщений: 7,093
09.07.2014, 23:03 #44
vlinx, вопрос, который тут действительно может поставить в затруднение, так это main и его параметры.
В стандарте нет версии с wchar_t. Но в VisualStudio уже об этом подумали, там "юникодность" программы переключается прямо в настройках проекта. И есть специальная версия - wmain.
То, что это непереносимо - плохо. Но в целом для программирования в win - это хорошо. Т.к. приложение должно максимально полно взаимодействовать с системой - начиная от внешнего вида UI и заканчивая API.

Добавлено через 1 минуту
Цитата Сообщение от vlinx Посмотреть сообщение
C++
1
2
3
4
std::wstring func(std::wstring const & p1, std::wstring const & p2) 
{
    return p1 + p2 + L".dll"; 
}
Fixed.
0
vlinx
1 / 1 / 0
Регистрация: 27.06.2014
Сообщений: 74
09.07.2014, 23:07  [ТС] #45
Всегда, вот всегда как дело касается кодировок, начинается какая-то фигня и мозголомство. Не только с кодом, да и при передаче данных, запросов на сервер, и все это из-за кодировок блин. Сколько раз уже замечал
0
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
09.07.2014, 23:07
Привет! Вот еще темы с ответами:

Компиляция C++ кода через консоль - C++
Есть простенький код: #include &lt;iostream&gt; #include &lt;vector&gt; int main(int argc, char *argv){ std::vector&lt;int&gt; vec; int num=1;...

Компиляция кода... не могу сообразить. - C++
Доброго времени суток уважаемые форумчане! Прошу помочь с решением проблемы: есть исходники memtest86+, скачал чтоб разобраться как...

Компиляция кода под конкретную ОС - C++
Есть ОС Windows, Linux, Android. Хочу понять базовые знание по тому как делается библиотека работающая на всех ОС. Допустим пишем...

Компиляция кода с ромбовидным наследованием - C++
Здравствуйте. Я написал элементарное наследование. На VS 2015 всё компилится, а на CLion нет. В чём может быть проблема? class A { ...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
Yandex
Объявления
09.07.2014, 23:07
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru